home *** CD-ROM | disk | FTP | other *** search
/ QuickTime 2.0 Developer Kit / QuickTime 2.0 Developer Kit.iso / pc / windows / qtw_201 / setup / samples / mplayer / moviewnd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-19  |  136.7 KB  |  3,456 lines

  1.  
  2. // ---------------------------------------------------------------------
  3. //
  4. // MovieWnd.c - Movie Player - QuickTime for Windows
  5. //
  6. //              Version 1.0
  7. //
  8. //              (c) Copyright 1988-1994 Apple Computer, Inc. All Rights Reserved.
  9. //
  10. // ---------------------------------------------------------------------
  11.  
  12.  
  13.  
  14. // Includes
  15. // --------
  16. #include <Windows.H>   // Required by Windows
  17. #include <commdlg.h>   // Required for PRINTDLG struct
  18. #include <stdio.h>     // Required for sprintf routine
  19. #include <sys\types.h> // Required for stat.h
  20. #include <sys\stat.h>  // Required for _stat routine
  21. #include <math.h>      // Required for abs()
  22. #include <string.h>    // Required for memset
  23.  
  24. #include <qtw.h>   // Interface to QuickTime
  25. #include <qtole.h> // Interface to qtole dll
  26.  
  27. #include "common.h" // Interface to common.c
  28.  
  29. #include "player.h"  // Interface to other *.c files
  30. #include "player.hr" // Defines used in *.rc files
  31.  
  32.  
  33. // Constants
  34. // ---------
  35. #define GETINFOMOVIEPROP      "Movie"
  36.  
  37.  
  38. // Message-Persistent Data
  39. // -----------------------
  40. static struct // Hungarian notation: g
  41.   {WORD        wMovieCount;            // Used during enumeration for
  42.                                        // duplication checking
  43.    BOOL        bCreating;              //   "    "       "
  44.    HWND        hwndFirstDup;           //   "    "       "
  45.    WORD        wMovieControllerHeight; // Height of movie controller
  46.    BOOL        bUpdatingInfo;          // Updating info dialog flag
  47.    char        szSelectFormat[30];     // Info dialog selection format string
  48.    char        szNoSelection[20];      // Info dialog "no selection" string
  49.    HICON       hmovieIcon;             // Movie frame icon
  50.    HCURSOR     hcursor;                // Current cursor. We need to set cursor
  51.                                        // during constrained resizing so class
  52.                                        // cursor must be set to NULL;
  53.    RECT        rcResizeRect;           // Rect used during constrained resizing
  54.    POINT       ptCursorOffset;         // Offset of cursor from edge of wnd rect
  55.    WORD        wSides;                 // Combined width of vertical size borders
  56.    WORD        wTBBorder;              // Combined width of horizontal size borders
  57.    WORD        wTopAndBottom;          // Difference in height between movie and
  58.                                        // movie window. This includes the movie
  59.                                        // controller
  60.    WORD        wSoundOnlyDefWidth;     // Default width of a sound only movie
  61.    WORD        wScaleWidth;            // Scale width used in constrained resize
  62.    WORD        wScaleHeight;           // Scale height used in constrained resize
  63.    BOOL        bFatResizeBorder;       // Flag that causes resize border to be
  64.                                        // drawn 2 pixels thicker
  65.    WNDPROC     lpOldGBProc;            // Original grow box proc
  66.    WNDPROC     lpNewGBProc;            // Subclassed grow box proc
  67.    HWND        hwndMaximizedMovie;     // Handle of maximized movie wnd
  68.    BOOL        bCapturedGrowBox;       // TRUE if the grow box input has
  69.                                        // been captured
  70.   } g;
  71.  
  72. // Macros
  73. // ----------------------
  74. #define ISKEYDOWN( vKey )  (GetKeyState( (int) (vKey) ) < 0 )
  75.  
  76.  
  77. // Exported callback functions
  78. // ----------------------------
  79. BOOL __export CALLBACK GetInfoDlgProc       (HWND, UINT, WPARAM, LPARAM);
  80. BOOL __export CALLBACK CheckDupEnumProc     (HWND, LPARAM);
  81.  
  82. BOOL __export CALLBACK ActionFilter   (MovieController, UINT, LPVOID, LONG);
  83.  
  84. BOOL __export CALLBACK MovieChildEnumProc   (HWND, LPARAM);
  85. LONG __export CALLBACK GBSubClassProc       (HWND, UINT, WPARAM, LPARAM);
  86.  
  87. // Internal Function Declarations
  88. // ------------------------------
  89. static LONG   NEAR PlayerMovieCreate        (HWND, LPARAM );
  90. static LONG   NEAR PlayerEditCommands       (HWND, WPARAM, WORD);
  91. static LONG   NEAR PlayerMovieCommands      (HWND, WPARAM, WORD);
  92. static LONG   NEAR PrintFrame               (HWND, LPPRINTDLG);
  93. static VOID   NEAR FillMovieInfo            (HWND, NPMOVIEDATA);
  94. static LONG   NEAR StartTheMovie            (NPMOVIEDATA);
  95. static LONG   NEAR StopTheMovie             (NPMOVIEDATA);
  96. static VOID   NEAR UpdateInfoFileName       (NPMOVIEDATA);
  97. static VOID   NEAR DisplayCurrentSelection  (NPMOVIEDATA);
  98. static LONG   NEAR ResizeMovieAndWindow     (HWND, BOOL, NPMOVIEDATA, WORD, WORD);
  99. static LONG   NEAR ResizeMovie              (NPMOVIEDATA, WORD, WORD);
  100. static LONG   NEAR InitializePopupMenus     (HWND, HMENU, int);
  101. static LONG   NEAR SetMinMaxInfo            (HWND, NPMOVIEDATA, MINMAXINFO FAR *);
  102. static VOID   NEAR ActivateTheController    (HWND, NPMOVIEDATA, BOOL);
  103. static LONG   NEAR PaintTheIcon             (HWND, NPMOVIEDATA);
  104. static HFONT  NEAR MakeAnArialFont          (HDC, int);
  105. static VOID   NEAR UpdateGBBoundsRect       (HWND, NPMOVIEDATA);
  106. static WORD   NEAR InitializeResize         (HWND, NPMOVIEDATA, WORD, POINT);
  107. static VOID   NEAR DrawTheFrameRect         (LPRECT, BOOL);
  108. static VOID   NEAR MoveTheMovieResizeRect   (HWND, NPMOVIEDATA,
  109.                                                           WORD, POINT, BOOL);
  110. static VOID   NEAR GetProportionalDimensions (NPMOVIEDATA, PWORD, PWORD, BOOL);
  111. static VOID   NEAR AdjustForMinProportionalSize(HWND, NPMOVIEDATA,
  112.                                                       LPWORD, LPWORD, BOOL);
  113. static BOOL   NEAR IsNormalSize             (LPRECT, NPMOVIEDATA);
  114. static BOOL   NEAR SubclassTheGrowBox       (HWND, NPMOVIEDATA);
  115. static BOOL   NEAR InitMaxWndGrowBoxResize  (HWND, POINT);
  116. static VOID   NEAR MoveTheFrameResizeRect   (HWND, POINT);
  117. static LONG   NEAR FixUpMovieTiling         (HWND, NPMOVIEDATA, LPWINDOWPOS);
  118. static VOID   NEAR SetOptionsDefaults       (HWND, NPMOVIEDATA);
  119. static VOID   NEAR PopulateOptionsStruct    (HWND, NPMOVIEDATA);
  120.  
  121.  
  122. // Function: PlayerMovieWndProc - Player Movie Window Procedure
  123. // --------------------------------------------------------------------
  124. // Parameters: As required by Microsoft Windows
  125. //
  126. // Returns:    Via DefMDIChildProc
  127. // --------------------------------------------------------------------
  128. LONG __export CALLBACK PlayerMovieWndProc
  129.     (HWND hwndMovie, UINT message, WPARAM wParam, LPARAM lParam)
  130.  
  131. {
  132.     NPMOVIEDATA      pMovieData;      // Temp -> to movie data struct
  133.     HMOVIEDATA       hMovieData;      // Temp handle of movie data
  134.     WNDENUMPROC      lpfnEnumMovies;  // -> enumeration proc
  135.     NPMOVIEDATA      pFirstMovieData; // Temp -> to movie data struct
  136.                                       // used during duplication processing
  137.     WORD             wMovieWidth;     // Movie normal width
  138.     WORD             wMovieHeight;    // Movie normal height
  139.     WORD             wWidth;          // Window width
  140.     WORD             wHeight;         // Window height
  141.     LRESULT          lRetVal;         // Return from DefMDIChildProc
  142.     POINT            ptCursor;        // Cursor position in screen coords.
  143.     LPQTOLE_OLEDATA  lpOleData;       // -> ole data
  144.     RECT             rcMovie;         // Bounds rect of movie within Movie controller client area
  145.     long             flSearch;        // for MovieSearchText
  146.  
  147.     static WORD      wResizeHitTestCode; // Equals the NC hit test code when
  148.                                          // resizing with SHIFT or CONTROL
  149.  
  150.  
  151.     pMovieData = (NPMOVIEDATA) GetWindowWord( hwndMovie, 0 );
  152.     if( pMovieData &&
  153.         MCIsPlayerMessage( pMovieData->mcMovieController,
  154.         hwndMovie, message, wParam, lParam ))
  155.         return DefMDIChildProc( hwndMovie, message, wParam, lParam );
  156.  
  157.     if (message == pMovieData->uiFindMessage) {
  158.         if (pMovieData->fr.Flags & FR_DIALOGTERM) {
  159.             PlayerSetActiveModeless(WA_INACTIVE,pMovieData->hwndSearch);
  160.             pMovieData->hwndSearch = NULL;
  161.             return 0;
  162.         }
  163.         PlayerSetActiveModeless (WA_ACTIVE, pMovieData->hwndSearch);
  164.         flSearch = findTextWrapAround | findTextUseOffset;
  165.         if (!(pMovieData->fr.Flags & FR_DOWN))
  166.             flSearch |= findTextReverseSearch;
  167.         if (pMovieData->fr.Flags & FR_MATCHCASE)
  168.             flSearch |= findTextCaseSensitive;
  169.         if (MovieSearchText (pMovieData->mMovie,
  170.             (LPBYTE) pMovieData->fr.lpstrFindWhat,
  171.             (LONG) lstrlen (pMovieData->fr.lpstrFindWhat),
  172.             flSearch,
  173.             NULL,
  174.             &pMovieData->tvSearch,
  175.             &pMovieData->lOffset) != noErr) {
  176.             CommonTellUser (PlayerQueryResources(),
  177.                 PLAYER_STRING_SEARCHFAIL,
  178.                 PLAYER_STRING_CAPTION,
  179.                 MB_OK );
  180.  
  181.         }
  182.  
  183.         return 0;
  184.     }
  185.  
  186.     switch( message ) {
  187.         case WM_CREATE:
  188.             // Load movie frame icon used by all instances
  189.             if( !g.hmovieIcon )
  190.                 g.hmovieIcon = LoadIcon( PlayerQueryResources(),
  191.                 MAKEINTRESOURCE( PLAYER_MOVIE_ICON ));
  192.             if( !g.hcursor )
  193.                 g.hcursor = LoadCursor( NULL, IDC_ARROW );
  194.  
  195.             return PlayerMovieCreate( hwndMovie, lParam );
  196.  
  197.         case WM_SIZE:
  198.             if( !pMovieData )
  199.                 break; // break to DefMDIChildProc
  200.  
  201.             wMovieWidth  = LOWORD( lParam );
  202.             if( HIWORD( lParam ) > g.wMovieControllerHeight )
  203.                 wMovieHeight = HIWORD( lParam ) - g.wMovieControllerHeight;
  204.             else
  205.                 wMovieHeight = 0;
  206.  
  207.             if( wParam ) // Minimizing, maximizing, etc
  208.             {
  209.                 if( wParam == SIZE_MAXIMIZED )
  210.                 // If subclass failed, remove grow box
  211.                 {
  212.                     if( IsZoomed( PlayerQueryFrameWindow()) ||
  213.                         !pMovieData->bGrowBoxSubclassed ) {
  214.                         SetRectEmpty( &pMovieData->rcGrowBox );
  215.                         MCDoAction( pMovieData->mcMovieController,
  216.                             mcActionSetGrowBoxBounds, &pMovieData->rcGrowBox );
  217.                     }
  218.                     else if( pMovieData->wMinMaxEtc == SIZE_MINIMIZED ) { // Reset grow box bounds rect
  219.                         UpdateGBBoundsRect( hwndMovie, pMovieData );
  220.                     }
  221.  
  222.                     if( pMovieData->wMinMaxEtc == SIZE_MINIMIZED )
  223.                         StartTheMovie( pMovieData );
  224.  
  225.                     g.hwndMaximizedMovie = hwndMovie;
  226.                     ResizeMovie( pMovieData, wMovieWidth, wMovieHeight);
  227.                 }
  228.                 else if( wParam == SIZE_MINIMIZED ) {
  229.                     SetRectEmpty( &pMovieData->rcGrowBox );
  230.                     MCDoAction( pMovieData->mcMovieController,
  231.                         mcActionSetGrowBoxBounds, &pMovieData->rcGrowBox );
  232.  
  233.                     StopTheMovie( pMovieData );
  234.  
  235.                     PaintTheIcon( hwndMovie, pMovieData );
  236.                 }
  237.  
  238.                 pMovieData->wMinMaxEtc = wParam;
  239.             }
  240.             else if( pMovieData->wMinMaxEtc ) // restoring
  241.             { // Reset grow box bounds rect
  242.                 UpdateGBBoundsRect( hwndMovie, pMovieData );
  243.  
  244.                 if( pMovieData->wMinMaxEtc == SIZE_MAXIMIZED ) {
  245.                     if( g.hwndMaximizedMovie == hwndMovie )
  246.                         g.hwndMaximizedMovie = NULL;
  247.  
  248.                     ResizeMovie( pMovieData, wMovieWidth, wMovieHeight);
  249.                 }
  250.                 else if( pMovieData->wMinMaxEtc == SIZE_MINIMIZED ) {
  251.                     StartTheMovie( pMovieData );
  252.                 }
  253.                 pMovieData->wMinMaxEtc = 0;
  254.             }
  255.             else if( pMovieData->bDisableSizeMsgProcessing ) { // Already processing create message, menu item or resizing
  256.                                                                // to aspect ratio or even multiple of pixels according
  257.                                                                // to key states in the last else under this message
  258.                 pMovieData->bDisableSizeMsgProcessing = FALSE;
  259.             }
  260.             else {
  261.                 ResizeMovie( pMovieData, wMovieWidth, wMovieHeight);
  262.             }
  263.  
  264.             // Need this for movie controller to repaint correctly
  265.             // when window is small
  266.             if( wResizeHitTestCode ||
  267.                 ( PlayerQueryMDIAction() == PLAYER_WINDOW_TILE ))
  268.                 InvalidateRect( hwndMovie, NULL, FALSE );
  269.  
  270.             break; // break to DefMDIChildProc
  271.  
  272.         case WM_MOVE:
  273.             if( !pMovieData ||
  274.                 ( pMovieData->wMinMaxEtc == SIZE_MAXIMIZED ) ||
  275.                 ( pMovieData->wMinMaxEtc == SIZE_MINIMIZED ))
  276.                 break; // break to DefMDIChildProc
  277.  
  278.             if( pMovieData->bDisableMoveMsgProcessing ) {
  279.                 // Already processing create message, menu item or resizing
  280.                 // to aspect ratio or even multiple of pixels according
  281.                 // to key states in the last else under this message
  282.                 pMovieData->bDisableMoveMsgProcessing = FALSE;
  283.             } 
  284.             else {
  285.                 GetMovieBox(pMovieData->mMovie ,&rcMovie);
  286.                 pMovieData->bDisableMoveMsgProcessing = TRUE;
  287.                 AlignWindow((WindowPtr)hwndMovie, FALSE, &rcMovie,NULL);
  288.             }
  289.             // Need to reset grow box bounds rect after a move because it is
  290.             // the client rect of the MDI frame window expressed in the client
  291.             // coordinates of the movie window
  292.             UpdateGBBoundsRect( hwndMovie, pMovieData );
  293.             break; // break to DefMDIChildProc
  294.  
  295.         case WM_WINDOWPOSCHANGING:
  296.             if( pMovieData &&
  297.                 ( PlayerQueryMDIAction() == PLAYER_WINDOW_TILE )) {
  298.                 FixUpMovieTiling( hwndMovie,
  299.                     pMovieData, (LPWINDOWPOS) lParam );
  300.             }
  301.  
  302.             break; // break to DefMDIChildProc
  303.  
  304.         case WM_COMMAND:
  305.             switch( wParam ) {
  306.                 case PLAYER_EDIT_COPY: // edit menu popup
  307.                 case PLAYER_EDIT_OPTIONS:
  308.                 case PLAYER_EDIT_CANCELSEL:
  309.                     return PlayerEditCommands
  310.                         ( hwndMovie, wParam, HIWORD( lParam ));
  311.  
  312.                 case PLAYER_MOVIE_SEARCH:
  313.                 case PLAYER_MOVIE_GETINFO:
  314.                 case PLAYER_MOVIE_STOPATEND:
  315.                 case PLAYER_MOVIE_LOOP:
  316.                 case PLAYER_MOVIE_BACKANDFORTH:
  317.                 case PLAYER_MOVIE_PLAYSELONLY:
  318.                 case PLAYER_MOVIE_HALFSIZE:
  319.                 case PLAYER_MOVIE_NORMALSIZE:
  320.                 case PLAYER_MOVIE_DOUBLESIZE:
  321.                 case PLAYER_MOVIE_SHOWPOSTER:
  322.                     return PlayerMovieCommands
  323.                         ( hwndMovie, wParam, HIWORD( lParam ));
  324.  
  325.                 default:
  326.                     break; // break to DefMDIChildProc
  327.             }
  328.  
  329.             break;
  330.  
  331.         // WM_USER messages
  332.  
  333.         case WM_PLAYER_PRINTFRAME:
  334.             return PrintFrame( hwndMovie, (LPPRINTDLG) lParam );
  335.  
  336.         case WM_PLAYER_INITPOPUPS:
  337.             return InitializePopupMenus
  338.                 ( hwndMovie, (HMENU) wParam, (int) LOWORD(lParam) );
  339.  
  340.         case WM_PLAYER_ACTIVATEMOVIE:
  341.             if( pMovieData ) {
  342.                 SetMovieActive( pMovieData->mMovie, TRUE );
  343.                 SetFocus( hwndMovie );
  344.             }
  345.  
  346.             return 0L;
  347.  
  348.         case WM_PLAYER_ACTIVATECONTROLLER:
  349.             if( pMovieData && pMovieData->mcMovieController )
  350.                 ActivateTheController( hwndMovie, pMovieData, TRUE );
  351.  
  352.             return 0L;
  353.  
  354.         case WM_PLAYER_PLAYTHEMOVIE: // Send by frame window when it is
  355.                                      // iconized or restored
  356.             if( pMovieData &&
  357.                 ( pMovieData->wMinMaxEtc != SIZE_MINIMIZED )) {
  358.                 if( (BOOL) wParam )
  359.                     StartTheMovie( pMovieData );
  360.                 else
  361.                     StopTheMovie( pMovieData );
  362.             }
  363.  
  364.             return 0L;
  365.  
  366.         case WM_PLAYER_UPDATEGBBOUNDSRECT:
  367.             // Frame window sends this message when size changes
  368.             if( !pMovieData ||
  369.                 ( pMovieData->wMinMaxEtc == SIZE_MINIMIZED ))
  370.                 return 0L;
  371.  
  372.             UpdateGBBoundsRect( hwndMovie, pMovieData );
  373.  
  374.             return 0L;
  375.  
  376.         // end WM_USER messages
  377.  
  378.         case WM_NCACTIVATE:
  379.             if( pMovieData && pMovieData->mcMovieController ) { // Activate or deactivate the controller
  380.                 if( (BOOL) wParam ) { // Post message to introduce a delay so that
  381.                                       // activation occurs after mouse click.
  382.                                       // Activate is called directly if PostMessage fails
  383.                     if( !PostMessage( hwndMovie,
  384.                         WM_PLAYER_ACTIVATECONTROLLER, TRUE, 0L ))
  385.                         ActivateTheController( hwndMovie, pMovieData, TRUE );
  386.                 }
  387.                 else {
  388.                     ActivateTheController( hwndMovie, pMovieData, FALSE );
  389.                 }
  390.             }
  391.  
  392.             break; // break to DefMDIChildProc
  393.  
  394.         case WM_GETMINMAXINFO:
  395.             SetMinMaxInfo( hwndMovie, pMovieData, (MINMAXINFO FAR*) lParam );
  396.             break; // break to DefMDIChildProc
  397.  
  398.         case WM_QUERYDRAGICON:
  399.             return MAKELONG( g.hmovieIcon, 0 );
  400.  
  401.         case WM_NCHITTEST:
  402.             lRetVal =  DefMDIChildProc
  403.                 ( hwndMovie, message, wParam, lParam );
  404.             if( pMovieData && pMovieData->bSoundOnly ) {
  405.                 switch( LOWORD( lRetVal )) {
  406.                     case HTTOP:
  407.                     case HTBOTTOM:
  408.                         return 0L;
  409.  
  410.                     case HTTOPLEFT:
  411.                     case HTBOTTOMLEFT:
  412.                         return HTLEFT;
  413.  
  414.                     case HTTOPRIGHT:
  415.                     case HTBOTTOMRIGHT:
  416.                         return HTRIGHT;
  417.  
  418.                     default:
  419.                         return lRetVal;
  420.                 }
  421.             }
  422.             else
  423.                 return lRetVal;
  424.  
  425.         case WM_NCLBUTTONDOWN: // We must do all border drag resizing
  426.                                // so we can do the constrained resizing
  427.             if( pMovieData &&
  428.                 ( wResizeHitTestCode = InitializeResize
  429.                 ( hwndMovie, pMovieData, wParam, MAKEPOINT( lParam )))) {
  430.                 SetCapture( hwndMovie );
  431.                 MoveTheMovieResizeRect( hwndMovie, pMovieData,
  432.                     wResizeHitTestCode, MAKEPOINT( lParam ), TRUE );
  433.                 return 0L;
  434.             }
  435.  
  436.             break; // break to DefMDIChildProc
  437.  
  438.         case WM_MOUSEMOVE:
  439.             if( wResizeHitTestCode ) {
  440.                 ptCursor = MAKEPOINT( lParam );
  441.                 ClientToScreen( hwndMovie, &ptCursor );
  442.                 MoveTheMovieResizeRect( hwndMovie, pMovieData,
  443.                     wResizeHitTestCode, ptCursor, FALSE );
  444.             }
  445.             else if( g.bCapturedGrowBox ) // This move is initiated in the
  446.                                           // grow box subclass proc.
  447.             {
  448.                 ptCursor = MAKEPOINT( lParam );
  449.                 ClientToScreen( hwndMovie, &ptCursor );
  450.                 MoveTheFrameResizeRect( hwndMovie, ptCursor );
  451.             }
  452.  
  453.             SetCursor( g.hcursor );
  454.             return 0L;
  455.  
  456.         case WM_LBUTTONUP:
  457.             if( wResizeHitTestCode ) {
  458.                 DrawTheFrameRect( &g.rcResizeRect, g.bFatResizeBorder );
  459.  
  460.                 ReleaseCapture();
  461.                 DrawTheFrameRect( NULL, FALSE ); // This cleans up
  462.                 ClipCursor( NULL );
  463.                 g.hcursor = LoadCursor( NULL, IDC_ARROW );
  464.  
  465.                 if( !pMovieData->bSoundOnly &&
  466.                     ( ISKEYDOWN( VK_CONTROL ) || ISKEYDOWN( VK_SHIFT ))) {
  467.                     wWidth  = g.rcResizeRect.right - g.rcResizeRect.left;
  468.                     wHeight = g.rcResizeRect.bottom - g.rcResizeRect.top;
  469.  
  470.                     AdjustForMinProportionalSize
  471.                         ( hwndMovie, pMovieData,
  472.                         &wWidth, &wHeight, ISKEYDOWN( VK_CONTROL ));
  473.  
  474.                     g.rcResizeRect.right  = g.rcResizeRect.left + wWidth;
  475.                     g.rcResizeRect.bottom = g.rcResizeRect.top + wHeight;
  476.                 }
  477.  
  478.                 MapWindowPoints( HWND_DESKTOP, PlayerQueryClientWindow(),
  479.                     (LPPOINT) &g.rcResizeRect, 2 );
  480.  
  481.                 MoveWindow( hwndMovie,
  482.                     g.rcResizeRect.left, g.rcResizeRect.top,
  483.                     g.rcResizeRect.right - g.rcResizeRect.left,
  484.                     g.rcResizeRect.bottom - g.rcResizeRect.top, TRUE );
  485.  
  486.                 // This needs to be after the MoveWindow call
  487.                 wResizeHitTestCode = 0;
  488.             }
  489.             else if( g.bCapturedGrowBox ) // This move is initiated in the
  490.                                           // grow box subclass proc.
  491.             {
  492.                 g.bCapturedGrowBox = FALSE;
  493.                 DrawTheFrameRect( &g.rcResizeRect, FALSE );
  494.  
  495.                 ReleaseCapture();
  496.                 DrawTheFrameRect( NULL, FALSE ); // This cleans up
  497.                 ClipCursor( NULL );
  498.  
  499.                 MoveWindow( PlayerQueryFrameWindow(),
  500.                     g.rcResizeRect.left, g.rcResizeRect.top,
  501.                     g.rcResizeRect.right - g.rcResizeRect.left,
  502.                     g.rcResizeRect.bottom - g.rcResizeRect.top, TRUE );
  503.             }
  504.  
  505.             return 0L;
  506.  
  507.         case WM_PAINT:
  508.             // We paint the icon but QTW takes care of all the painting
  509.             // otherwise.
  510.             if( pMovieData && IsIconic( hwndMovie ))
  511.                 return PaintTheIcon( hwndMovie, pMovieData );
  512.             break; // break to DefMDIChildProc
  513.  
  514.         case WM_DESTROY:
  515.             if( ( lpOleData = PlayerQueryOleData()) && lpOleData->lpqtoleServer )
  516.                 PopulateOptionsStruct( hwndMovie, pMovieData );
  517.             break; // break to DefMDIChildProc
  518.  
  519.         case WM_NCDESTROY:
  520.             if( !pMovieData )
  521.                 break;
  522.  
  523.             if( pMovieData->lpFilterProc ) {
  524.                 MCSetActionFilter
  525.                     ( pMovieData->mcMovieController, NULL, 0L );
  526.                 FreeProcInstance( (FARPROC ) pMovieData->lpFilterProc );
  527.                 pMovieData->lpFilterProc = NULL;
  528.             }
  529.  
  530.             if( pMovieData->hwndGetInfo )
  531.                 DestroyWindow( pMovieData->hwndGetInfo );
  532.  
  533.             if( pMovieData->hwndSearch )
  534.                 DestroyWindow( pMovieData->hwndSearch );
  535.  
  536.             if( pMovieData->mcMovieController )
  537.                 DisposeMovieController( pMovieData->mcMovieController );
  538.             if( pMovieData->mMovie )
  539.                 DisposeMovie( pMovieData->mMovie );
  540.  
  541.             // Last instance destroys icon and grow box subclass proc
  542.             if( PlayerQueryNumMovies() <= 1 ) {
  543.                 if( g.hmovieIcon )
  544.                     DestroyIcon( g.hmovieIcon );
  545.                 g.hmovieIcon = NULL;
  546.  
  547.                 // Free the grow box subclass proc
  548.                 if( g.lpNewGBProc ) {
  549.                     FreeProcInstance( (FARPROC) g.lpNewGBProc );
  550.                     g.lpNewGBProc = NULL;
  551.                 }
  552.                 g.lpOldGBProc = NULL;
  553.             }
  554.             else { // Check for duplicates
  555.                 g.wMovieCount  = 0;
  556.                 g.bCreating    = FALSE;
  557.                 g.hwndFirstDup = NULL;
  558.  
  559.                 if( lpfnEnumMovies = (WNDENUMPROC) MakeProcInstance
  560.                     ( (FARPROC) CheckDupEnumProc, PlayerQueryInstance())) {
  561.                     EnumChildWindows( PlayerQueryClientWindow(),
  562.                         lpfnEnumMovies, MAKELPARAM( hwndMovie, 0 ));
  563.                     FreeProcInstance( (FARPROC) lpfnEnumMovies );
  564.                 }
  565.  
  566.                 // if no dups, eliminate :1 on first
  567.                 // hwndFirstDup is set in CheckDupEnumProc
  568.                 if( ( g.wMovieCount == 1 ) && g.hwndFirstDup &&
  569.                     ( pFirstMovieData = (NPMOVIEDATA)
  570.                     GetWindowWord( g.hwndFirstDup, 0 ))) {
  571.                     pFirstMovieData->wDuplicationIndex = 0;
  572.                     SetWindowText( g.hwndFirstDup,
  573.                         pFirstMovieData->szMovieName );
  574.                 }
  575.             }
  576.  
  577.             // Tell OLE that window is closed. Movie has been disposed
  578.             // qtole.dll used hwndObject so don't null the handle in struct
  579.             pMovieData->qtoleOptions.mMovie = NULL;
  580.  
  581.             if( ( lpOleData = PlayerQueryOleData()) && lpOleData->lpqtoleServer )
  582.                 QTOLE_ClosingDocWnd( lpOleData,
  583.                 (LPQTOLE_OPTIONS) &pMovieData->qtoleOptions );
  584.  
  585.             LocalUnlock( hMovieData =
  586.                 (HMOVIEDATA) LocalHandle( pMovieData ));
  587.             LocalFree( hMovieData );
  588.             SetWindowWord( hwndMovie, 0, 0);
  589.  
  590.             // Update the movie count in the frame window globals
  591.             SendMessage( PlayerQueryFrameWindow(),
  592.                 WM_PLAYER_MOVIEDELETED, (WPARAM) hwndMovie, 0L );
  593.  
  594.             break; // break to DefMDIChildProc
  595.  
  596.     }
  597.  
  598.     return DefMDIChildProc( hwndMovie, message, wParam, lParam );
  599. }
  600.  
  601.  
  602. // Function: PlayerMovieCreate - process WM_CREATE message
  603. // --------------------------------------------------------------------
  604. // Parameters: HWND        hwndMovie;      Handle of movie window
  605. //             LPARAM      lParam;         lParam of WM_CREATE message
  606. //
  607. // Returns:    0 if OK, else returns -1 to kill app
  608. // --------------------------------------------------------------------
  609. static LONG NEAR PlayerMovieCreate( HWND hwndMovie, LPARAM lParam )
  610.  
  611. {
  612.     NPMOVIEDATA        pMovieData;             // Temp -> to movie data struct
  613.     HMOVIEDATA         hMovieData;             // Handle to movie data struct
  614.     LPMDICREATESTRUCT  lpmdicreate;            // MDI create struct
  615.     MovieFile          movMovieFile;           // Movie file handle
  616.     char               szBuffer[MAX_PATH_LEN]; // Temp buffer
  617.     struct _stat       statbuf;                // File statictics struct
  618.     WORD               wIDString;              // Resource string id
  619.     DWORD              dwBytes;                // File size
  620.     OSErr              oserr;                  // Error return
  621.     RECT               rcMovie;                // Movie rect
  622.     RECT               rcWindow;               // Window rect
  623.     RECT               rcController;           // Controller rect
  624.     POINT              ptCorner;               // Upper Left corner of movie wnd
  625.     WORD               wWidth;                 // Width of window
  626.     WORD               wHeight;                // Height of window
  627.     RECT               rcclientClient;         // Client rect of MDI client wnd
  628.     int                nDiff;                  // Temp
  629.     WNDENUMPROC        lpfnEnumMovies;         // -> to enumeration proc
  630.     LPSTR              lpName;                 // Temp -> movie name
  631.     LONG               lStyle;                 // Temp window style
  632.     UserData           udUserData;             // Handle to user data
  633.     HGLOBAL            ghMem;                  // Global mem used to get 'loop' user data
  634.     LONG               lSizeData;              // Size of 'loop' user data
  635.     LPSTR              lpUserData;             // -> 'loop' user data
  636.     int                i;                      // Loop counter
  637.     QTOLE_OPENWND      qtoleOpenWnd;           // Ole open wnd struct
  638.     LPQTOLE_OLEDATA    lpOleData;              // -> ole data
  639.     int                nLoop;
  640.  
  641.  
  642.     pMovieData = (NPMOVIEDATA) NULL;
  643.  
  644.     if( !(hMovieData = (HMOVIEDATA)
  645.         LocalAlloc( LPTR, sizeof( MOVIEDATASTRUCT )))) {
  646.         CommonTellUser( PlayerQueryResources(),
  647.             PLAYER_STRING_NOMEMORY, NULL, MB_OK );
  648.         goto Failed;
  649.     }
  650.     pMovieData = (NPMOVIEDATA) LocalLock( hMovieData );
  651.     SetWindowWord( hwndMovie, 0, (WORD) pMovieData );
  652.  
  653.     // mdi struct filled before call to MDI create in LaunchMovieWnd
  654.     lpmdicreate = (LPMDICREATESTRUCT)
  655.         ((LPCREATESTRUCT) lParam)->lpCreateParams;
  656.  
  657.     lstrcpy( pMovieData->szMoviePath, (LPSTR) lpmdicreate -> lParam );
  658.     lstrcpy( pMovieData->szMovieName, (LPSTR) lpmdicreate -> szTitle );
  659.  
  660.     // register the message used by find/replace
  661.     pMovieData->uiFindMessage = RegisterWindowMessage (FINDMSGSTRING);
  662.  
  663.     // Strip off and save extension so that name fits better
  664.     // on title bar of window
  665.     pMovieData->szMovieExt[0] = '\0';
  666.     lpName = pMovieData->szMovieName;
  667.     while( *lpName ) {
  668.         if( *lpName == '.' ) {
  669.             lstrcpy( pMovieData->szMovieExt, lpName );
  670.             *lpName = '\0';
  671.             SetWindowText( hwndMovie, pMovieData->szMovieName );
  672.             break;
  673.         }
  674.         else
  675.             lpName = AnsiNext( lpName );
  676.     }
  677.  
  678.     if( ( oserr = OpenMovieFile( pMovieData->szMoviePath,
  679.         &movMovieFile, OF_READ )) == 0 ) {
  680.         oserr = NewMovieFromFile( &pMovieData->mMovie,
  681.             movMovieFile, NULL, NULL, 0, NULL );
  682.         CloseMovieFile( movMovieFile );
  683.     }
  684.  
  685.     if( oserr ) {
  686.         if( oserr == insufficientMemory )
  687.             wIDString = PLAYER_STRING_NOMEMORY;
  688.         else if( oserr == invalidDataRef )
  689.             wIDString = PLAYER_STRING_INVALIDDATAREF;
  690.         else
  691.             wIDString = PLAYER_STRING_NEWMOVIEERR;
  692.  
  693.         CommonTellUser( PlayerQueryResources(),
  694.             wIDString, PLAYER_STRING_CAPTION,
  695.             MB_OK, (LPSTR) lpmdicreate -> szTitle );
  696.         goto Failed;
  697.     }
  698.  
  699.     // Check for duplicates. Fix up titles if necessary
  700.     // Initialize globals used during enumeration
  701.     g.wMovieCount = 1;
  702.     g.bCreating =  TRUE;
  703.     if( ( PlayerQueryNumMovies() > 0 ) &&
  704.         ( lpfnEnumMovies = (WNDENUMPROC) MakeProcInstance
  705.         ( (FARPROC) CheckDupEnumProc, PlayerQueryInstance()))) {
  706.         EnumChildWindows( PlayerQueryClientWindow(),
  707.             lpfnEnumMovies, MAKELPARAM( hwndMovie, 0 ));
  708.         FreeProcInstance( (FARPROC) lpfnEnumMovies );
  709.  
  710.         // Fix up title if duplicate
  711.         // Title of 1st dup is fixed up during enum
  712.         if( g.wMovieCount > 1 ) {
  713.             pMovieData->wDuplicationIndex = g.wMovieCount;
  714.             wsprintf( szBuffer, "%s:%u",
  715.                 (LPSTR) pMovieData->szMovieName,
  716.                 pMovieData->wDuplicationIndex );
  717.             SetWindowText( hwndMovie, szBuffer );
  718.         }
  719.     }
  720.  
  721.     // file size  Note: _stat path name is in OEM char set
  722.     lstrcpy( szBuffer, pMovieData->szMoviePath );
  723.     AnsiToOem( szBuffer, szBuffer );
  724.     if( (_stat( szBuffer, &statbuf )) == 0 ) {
  725.         if( statbuf.st_size < 1000L ) {
  726.             dwBytes = (DWORD) statbuf.st_size;
  727.             wIDString = PLAYER_STRING_SIZEBYTES;
  728.         }
  729.         else {
  730.             dwBytes = (DWORD) ( statbuf.st_size / 1000L );
  731.             wIDString = PLAYER_STRING_SIZEKBYTES;
  732.         }
  733.  
  734.         LoadString( PlayerQueryResources(),
  735.             wIDString, szBuffer, sizeof( szBuffer ));
  736.         wsprintf( pMovieData->szFileSize, szBuffer, dwBytes );
  737.     }
  738.  
  739.     pMovieData->bSoundOnly = FALSE;
  740.     GetMovieBox(  pMovieData->mMovie, &rcMovie );
  741.     OffsetRect( &rcMovie, -rcMovie.left, -rcMovie.top );
  742.     pMovieData->cx = rcMovie.right;
  743.     pMovieData->cy = rcMovie.bottom;
  744.     pMovieData->bSoundOnly = (pMovieData->cx == 0) && (pMovieData->cy == 0);
  745.  
  746.     pMovieData->idMovieInfo.idSize = sizeof( ImageDescription );
  747.     pMovieData->oserrVideoInfo =
  748.         GetVideoInfo( pMovieData->mMovie, &pMovieData->idMovieInfo );
  749.  
  750.  
  751.     pMovieData->sdSoundInfo.descSize = sizeof( SoundDescription );
  752.     pMovieData->oserrSoundInfo =
  753.         GetSoundInfo( pMovieData->mMovie, &pMovieData->sdSoundInfo );
  754.  
  755.  
  756.  
  757.     // Set copy option default values
  758.     SetOptionsDefaults( hwndMovie, pMovieData );
  759.  
  760.     // Instantiate the movie controller
  761.     if( !pMovieData->bSoundOnly ) // Call only if there is video
  762.  
  763.     // Now resize window if default option is half or double size
  764.     {
  765.         if( pMovieData->qtoleOptions.bSizeHalf ) {
  766.             rcMovie.right  /= 2;
  767.             rcMovie.bottom /= 2;
  768.         }
  769.         else if( pMovieData->qtoleOptions.bSizeDouble ) {
  770.             rcMovie.right  *= 2;
  771.             rcMovie.bottom *= 2;
  772.         }
  773.     }
  774.  
  775.     // Movie with no video or no rect gets a default width to pass to
  776.     // NewMovieController
  777.     if( pMovieData->bSoundOnly || IsRectEmpty( &rcMovie )) {
  778.         rcMovie.left = rcMovie.top = 0;
  779.         rcMovie.right = 8 * GetSystemMetrics( SM_CXVSCROLL );
  780.         rcMovie.bottom = 0;
  781.     }
  782.  
  783.     if( !( pMovieData->mcMovieController =
  784.         NewMovieController( pMovieData->mMovie, &rcMovie,
  785.         mcTopLeftMovie | mcScaleMovieToFit, hwndMovie ))) {
  786.         CommonTellUser( PlayerQueryResources(),
  787.             PLAYER_STRING_NOCONTROLLER, PLAYER_STRING_CAPTION, MB_OK );
  788.         goto Failed;
  789.     }
  790.     MCDoAction( pMovieData->mcMovieController, mcActionPlay, (LPVOID) 0 );
  791.  
  792.     // Set default values from embedding option default
  793.     //      UpdateMovieForOptions( hwndMovie, pMovieData, FALSE );
  794.  
  795.     // Subclass the movie controller grow box for use when a
  796.     // movie window is maximized
  797.     pMovieData->bGrowBoxSubclassed =
  798.         SubclassTheGrowBox( hwndMovie, pMovieData );
  799.  
  800.     // Override loop mode depending on user data
  801.     ghMem = NULL;
  802.     nLoop = 0;
  803.     if( ( udUserData = GetMovieUserData( pMovieData->mMovie )) &&
  804.         ( CountUserDataType( udUserData,
  805.         QTFOURCC( 'L', 'O', 'O', 'P' )) > 0 )) {
  806.         pMovieData->qtoleOptions.bLoop           = TRUE;
  807.         pMovieData->qtoleOptions.bLoopPalindrome = FALSE;
  808.         if( ( ghMem = GlobalAlloc( GHND, 16L )) &&
  809.             !GetUserData( udUserData, &ghMem,
  810.             QTFOURCC( 'L', 'O', 'O', 'P' ), 1L, &lSizeData ) &&
  811.             ( lSizeData > 0L )) {
  812.             lpUserData = (LPSTR) GlobalLock( ghMem );
  813.             for( i=0; i < lSizeData; i++ ) {
  814.                 if( *lpUserData++ != '\0' ) {
  815.                     pMovieData->qtoleOptions.bLoop           = FALSE;
  816.                     pMovieData->qtoleOptions.bLoopPalindrome = TRUE;
  817.                     break;
  818.                 }
  819.             }
  820.             GlobalUnlock( ghMem );
  821.         }
  822.         if( ghMem )
  823.             GlobalFree( ghMem );
  824.     }
  825.  
  826.     // Now tell the movie controller about the loop mode
  827.     MCDoAction( pMovieData->mcMovieController, mcActionSetLooping,
  828.         (LPVOID) ( pMovieData->qtoleOptions.bLoop ||
  829.         pMovieData->qtoleOptions.bLoopPalindrome ));
  830.     MCDoAction( pMovieData->mcMovieController, mcActionSetLoopIsPalindrome,
  831.         (LPVOID) pMovieData->qtoleOptions.bLoopPalindrome );
  832.  
  833.     // Assume that the controller is attached
  834.     // Get the default UL corner of window
  835.     GetWindowRect( hwndMovie, &rcWindow );
  836.     MapWindowPoints( HWND_DESKTOP, PlayerQueryClientWindow(),
  837.         (LPPOINT) &rcWindow, 2 );
  838.     ptCorner = *((LPPOINT) &rcWindow.left );
  839.  
  840.     // This includes the movie AND the moviecontroller rect
  841.     MCGetControllerBoundsRect
  842.         ( pMovieData->mcMovieController, &rcController );
  843.     rcWindow = rcController;
  844.     // At this point rcController == client rect of window
  845.  
  846.     // Save controller height
  847.     g.wMovieControllerHeight =
  848.         ( rcWindow.bottom - rcWindow.top ) -
  849.         ( rcMovie.bottom - rcMovie.top );
  850.  
  851.     // Remove maximize box if sound only movie
  852.     if( pMovieData->bSoundOnly ) {
  853.         lStyle = GetWindowLong( hwndMovie, GWL_STYLE );
  854.         lStyle &= ~WS_MAXIMIZEBOX;
  855.         SetWindowLong( hwndMovie, GWL_STYLE, lStyle );
  856.     }
  857.  
  858.     AdjustWindowRect( &rcWindow,
  859.         GetWindowLong( hwndMovie, GWL_STYLE ), FALSE );
  860.     // rcWindow now contains the size of the window
  861.  
  862.     wWidth  = rcWindow.right  - rcWindow.left;
  863.     wHeight = rcWindow.bottom - rcWindow.top;
  864.     OffsetRect( &rcWindow, ptCorner.x - rcWindow.left,
  865.         ptCorner.y - rcWindow.top );
  866.     // rcWindow now contains the resized window positioned so that
  867.     // the UL corner is at the MDI default position
  868.  
  869.     // Now stash some dimensions needed later. Only need to do this once
  870.     if( pMovieData->bSoundOnly && !g.wSoundOnlyDefWidth ) {
  871.         g.wSoundOnlyDefWidth = wWidth;
  872.     }
  873.     if( !g.wSides ) {
  874.         g.wSides    = ( rcWindow.right - rcWindow.left ) -
  875.             ( rcController.right - rcController.left );
  876.         g.wTBBorder = ( rcWindow.bottom - rcWindow.top ) -
  877.             ( rcController.bottom - rcController.top );
  878.         g.wTopAndBottom = g.wMovieControllerHeight + g.wTBBorder;
  879.     }
  880.  
  881.  
  882.     // Now see if it will fit on screen.
  883.     GetClientRect( PlayerQueryClientWindow(), &rcclientClient );
  884.     if( rcWindow.right > rcclientClient.right ) { // extends beyond right border
  885.                                                   // Try to shift it to the left
  886.         nDiff = rcclientClient.right - wWidth;
  887.         rcWindow.left  = max( 0, nDiff );
  888.         rcWindow.right = rcWindow.left + wWidth;
  889.     }
  890.  
  891.     if( rcWindow.bottom > rcclientClient.bottom ) { // extends beyond bottom
  892.                                                     // Try to shift it up
  893.         nDiff = rcclientClient.bottom - wHeight;
  894.         rcWindow.top    = max( 0, nDiff );
  895.         rcWindow.bottom = rcWindow.top + wHeight;
  896.     }
  897.  
  898.     // Resize the window after disabling WM_SIZE processing
  899.     // In the unusual case that the controller is smaller than
  900.     // the smallest possible client, we stretch the controller
  901.     pMovieData->bDisableSizeMsgProcessing = TRUE;
  902.     MoveWindow( hwndMovie,
  903.         rcWindow.left, rcWindow.top, wWidth, wHeight, FALSE );
  904.  
  905.     // If movie is smaller than minimum window size, resize movie to
  906.     // fill the window
  907.     GetClientRect( hwndMovie, &rcWindow );
  908.     if( !EqualRect( &rcWindow, &rcController ))
  909.         MCSetControllerBoundsRect
  910.         ( pMovieData->mcMovieController, &rcWindow );
  911.  
  912.     // Size message turns this off, turn in on again for next
  913.     // WM_SIZE message generated by standard "create a window" processing
  914.     pMovieData->bDisableSizeMsgProcessing = TRUE;
  915.  
  916.     // Post message to activate the movie
  917.     // Post message is used to avoid a extra paint of the movie which
  918.     // causes a flash during the window creation
  919.     // SendMessage is called if PostMessage fails
  920.     if( !PostMessage( hwndMovie, WM_PLAYER_ACTIVATEMOVIE, 0, 0L ))
  921.         SendMessage( hwndMovie, WM_PLAYER_ACTIVATEMOVIE, 0, 0L );
  922.  
  923.     // Set Action filter to look for selection changes and grow box resizing.
  924.     // Do this after earlier resizing to avoid having to block filter messages
  925.     // generated during creation
  926.     if( pMovieData->lpFilterProc =
  927.         (MCActionFilter) MakeProcInstance
  928.         ( (FARPROC) ActionFilter, PlayerQueryInstance())) {
  929.         MCSetActionFilter( pMovieData->mcMovieController,
  930.             pMovieData->lpFilterProc, MAKELONG( pMovieData, hwndMovie ));
  931.     }
  932.  
  933.     // Tell qtole.dll that movie has been opened
  934.     if( ( lpOleData = PlayerQueryOleData()) && lpOleData->lpqtoleServer ) {
  935.         qtoleOpenWnd.lStructSize  = sizeof( qtoleOpenWnd );
  936.         qtoleOpenWnd.lVersion     = VERSION_1;
  937.         qtoleOpenWnd.wObjectType  = MOVIE_OBJECT;
  938.         qtoleOpenWnd.hwndObject   = hwndMovie;
  939.         qtoleOpenWnd.lpObjectPath = pMovieData->szMoviePath;
  940.         qtoleOpenWnd.lpObjectName = pMovieData->szMovieName;
  941.  
  942.         QTOLE_OpeningNewObjectWnd( lpOleData, &qtoleOpenWnd );
  943.     }
  944.  
  945.     return  0L;
  946.  
  947.  Failed:
  948.     SetWindowWord( hwndMovie, 0, 0 );
  949.     if( pMovieData )
  950.         LocalUnlock( hMovieData );
  951.     if( hMovieData )
  952.         LocalFree  ( hMovieData );
  953.  
  954.     return -1;
  955.  
  956. }
  957.  
  958. // Function: CheckDupEnumProc - Checks for duplicate pictures and
  959. //                              fixes up titles if there are any
  960. // --------------------------------------------------------------------
  961. // Parameters: As required by Microsoft Windows
  962. //
  963. // Returns:    Always TRUE;
  964. // --------------------------------------------------------------------
  965. BOOL __export CALLBACK CheckDupEnumProc( HWND hwnd, LPARAM lParam )
  966.  
  967. // Look for duplicate pictures. Test is on path rather than just name
  968.  
  969. {
  970.     char            szBuffer[50];     // Temp buffer
  971.     HWND            hwndActiveMovie;  // Handle of active movie wnd
  972.     NPMOVIEDATA     pMovieData;       // -> enum wnd movie data struct
  973.     NPMOVIEDATA     pActiveMovieData; // -> active wnd movie data struct
  974.  
  975.     // Skip active movie
  976.     if( ( hwndActiveMovie = (HWND) LOWORD( lParam )) == hwnd )
  977.         return TRUE;
  978.  
  979.     if( !GetClassName( hwnd, szBuffer, sizeof( szBuffer )) ||
  980.         lstrcmpi( szBuffer, PLAYER_MOVIE_CLASS ))
  981.         return TRUE;
  982.  
  983.     pMovieData = (NPMOVIEDATA) GetWindowWord( hwnd, 0 );
  984.     pActiveMovieData = (NPMOVIEDATA) GetWindowWord( hwndActiveMovie, 0 );
  985.     if( !pMovieData || !pActiveMovieData )
  986.         return TRUE;
  987.  
  988.     if( !lstrcmpi( pMovieData->szMoviePath,
  989.         pActiveMovieData->szMoviePath )) { // Found a duplicate
  990.         g.wMovieCount++;
  991.         if( g.bCreating ) {
  992.             if( pMovieData->wDuplicationIndex == 0 ) {
  993.                 pMovieData->wDuplicationIndex = 1;
  994.                 wsprintf( szBuffer, "%s:%u",
  995.                     (LPSTR) pMovieData->szMovieName,
  996.                     pMovieData->wDuplicationIndex );
  997.                 SetWindowText( hwnd, szBuffer );
  998.             }
  999.         }
  1000.         else {
  1001.             if( pMovieData->wDuplicationIndex >
  1002.                 pActiveMovieData->wDuplicationIndex ) {
  1003.                 pMovieData->wDuplicationIndex--;
  1004.                 wsprintf( szBuffer, "%s:%u",
  1005.                     (LPSTR) pMovieData->szMovieName,
  1006.                     pMovieData->wDuplicationIndex );
  1007.                 SetWindowText( hwnd, szBuffer );
  1008.             }
  1009.             if( pMovieData->wDuplicationIndex == 1 )
  1010.                 g.hwndFirstDup = hwnd;
  1011.         }
  1012.  
  1013.         if( pMovieData->hwndGetInfo &&
  1014.             !PostMessage( pMovieData->hwndGetInfo,
  1015.             WM_PLAYER_INFO_UPDATEFILENAME, 0, 0L ))
  1016.             SendMessage( pMovieData->hwndGetInfo,
  1017.             WM_PLAYER_INFO_UPDATEFILENAME, 0, 0L );
  1018.     }
  1019.  
  1020.     return TRUE;
  1021. }
  1022.  
  1023.  
  1024. // Function: PlayerEditCommands - Process WM_COMMAND, Edit popup messages
  1025. // --------------------------------------------------------------------
  1026. // Parameters: HWND   hwndMovie;      Handle of movie window
  1027. //             WORD   wIDItem;        Menu or control id
  1028. //             WORD   wNotifyCode;    notification message
  1029. //
  1030. // Returns:    LONG   generally 0L
  1031. // --------------------------------------------------------------------
  1032. static LONG NEAR PlayerEditCommands
  1033.                     (HWND hwndMovie, WPARAM wIDItem, WORD wNotifyCode )
  1034.  
  1035. {
  1036.     NPMOVIEDATA      pMovieData;                           // -> movie data struct
  1037.     TimeRecord       trZeroTime;                           // Zero time
  1038.     OSErr            oserr;                                // Errror return value
  1039.     WORD             wIDString;                            // ID of error string
  1040.     TimeValue        tvSelectionStart,tvSelectionDuration; // for text extent
  1041.     TimeValue        tvMovieTime;
  1042.     LPQTOLE_OLEDATA  lpOleData;                            // -> ole data
  1043.  
  1044.     if( !(pMovieData = (NPMOVIEDATA) GetWindowWord( hwndMovie, 0 ))) {
  1045.         CommonTellUser( PlayerQueryResources(),
  1046.             PLAYER_STRING_NOMOVIEDATA, PLAYER_STRING_CAPTION, MB_OK );
  1047.         return 0L;
  1048.     }
  1049.  
  1050.     switch( wIDItem ) {
  1051.         case PLAYER_EDIT_COPY:
  1052.             if( IsIconic( hwndMovie ))
  1053.                 return 0L;
  1054.  
  1055.             // If ole, let ole do the copy
  1056.             if( ( lpOleData = PlayerQueryOleData()) && lpOleData->lpqtoleServer ) {
  1057.                 PopulateOptionsStruct( hwndMovie, pMovieData );
  1058.  
  1059.                 QTOLE_Copy( lpOleData, (LPQTOLE_OPTIONS) &pMovieData->qtoleOptions );
  1060.  
  1061.                 // We must compensate for an error in certain drivers by
  1062.                 // resetting the palette back the way we found it
  1063.                 MCDoAction( pMovieData->mcMovieController,
  1064.                     mcActionSetFlags, (LPVOID) mcFlagsUseWindowPalette );
  1065.             }
  1066.             else // No ole so do copy here
  1067.             {
  1068.                 OpenClipboard( hwndMovie );
  1069.                 EmptyClipboard();
  1070.  
  1071.                 tvMovieTime = GetMovieTime(pMovieData->mMovie,NULL);
  1072.                 GetMovieSelection(pMovieData->mMovie,
  1073.                     &tvSelectionStart,&tvSelectionDuration);
  1074.                 if (((long)tvSelectionStart < 0L) || ((long)tvSelectionDuration <= 0L)) {
  1075.                     tvSelectionStart = GetMovieTime(pMovieData->mMovie,NULL);
  1076.                     tvSelectionDuration = 1L;
  1077.                 }
  1078.  
  1079.                 // ignore clipboard errors...they get what's there
  1080.  
  1081.                 oserr = PutMovieIntoTypedHandle(
  1082.                     pMovieData->mMovie,
  1083.                     (Track)0L,
  1084.                     QTFOURCC('T','E','X','T'), // text track
  1085.                     NULL,                      // onto clipboard
  1086.                     tvSelectionStart,tvSelectionDuration,
  1087.                     0,0
  1088.                     );
  1089.                                                // dib contains a clut (except for 24 bit DIB)
  1090.                 if (oserr != insufficientMemory) {
  1091.                     oserr = PutMovieIntoTypedHandle(
  1092.                         pMovieData->mMovie,
  1093.                         (Track)0L,
  1094.                         QTFOURCC('D','I','B',' '), // visual track(s)
  1095.                         NULL,                      // onto clipboard
  1096.                         tvMovieTime,1L,
  1097.                         0,0
  1098.                         );
  1099.                 }
  1100.                 // bmp is posted to clipboard with CLUT
  1101.                 if (oserr != insufficientMemory) {
  1102.                     oserr = PutMovieIntoTypedHandle(
  1103.                         pMovieData->mMovie,
  1104.                         (Track)0L,
  1105.                         QTFOURCC('B','M','P',' '), // visual track(s)
  1106.                         NULL,                      // onto clipboard
  1107.                         tvMovieTime,1L,
  1108.                         0,0
  1109.                         );
  1110.                 }
  1111.                 CloseClipboard();
  1112.                 switch (oserr) {
  1113.                     case noErr:
  1114.                         wIDString = 0;
  1115.                         break;
  1116.                     case insufficientMemory:
  1117.                         wIDString = PLAYER_STRING_NOMEMORY;
  1118.                         break;
  1119.                     default:
  1120.                         wIDString = PLAYER_STRING_COPYFAILED;
  1121.                         break;
  1122.  
  1123.                 }
  1124.                 if (wIDString) {
  1125.                     CommonTellUser( PlayerQueryResources(),
  1126.                         wIDString, PLAYER_STRING_CAPTION, MB_OK);
  1127.                 }
  1128.  
  1129.                 return 0L;
  1130.  
  1131.             }
  1132.  
  1133.             return 0L;
  1134.  
  1135.         case PLAYER_EDIT_OPTIONS:
  1136.             PopulateOptionsStruct( hwndMovie, pMovieData );
  1137.  
  1138.             if( PlayerGetOptions( hwndMovie, &pMovieData->qtoleOptions ))
  1139.                 UpdateMovieForOptions( hwndMovie, pMovieData, FALSE );
  1140.  
  1141.             return 0L;
  1142.  
  1143.         case PLAYER_EDIT_CANCELSEL:
  1144.             trZeroTime.scale = GetMovieTimeScale( pMovieData->mMovie );
  1145.             trZeroTime.value.dwHi = 0L;
  1146.  
  1147.             trZeroTime.value.dwLo = (DWORD) -1L;
  1148.             trZeroTime.base       = TIMEBASE_DEFAULT;
  1149.             // Set beginning of selection to zero
  1150.             MCDoAction( pMovieData->mcMovieController,
  1151.                 mcActionSetSelectionBegin, (LPVOID) &trZeroTime );
  1152.             // Set duration to zero
  1153.             trZeroTime.value.dwLo = 0L;
  1154.             trZeroTime.base       = NULL;
  1155.             MCDoAction( pMovieData->mcMovieController,
  1156.                 mcActionSetSelectionDuration, (LPVOID) &trZeroTime );
  1157.  
  1158.             return 0L;
  1159.     }
  1160.  
  1161.     return 0L; // should never get here
  1162.  
  1163. }
  1164.  
  1165.  
  1166. // Function: PlayerMovieCommands - Process WM_COMMAND, Movie popup messages
  1167. // --------------------------------------------------------------------
  1168. // Parameters: HWND          hwndMovie;      Handle of movie window
  1169. //             WORD          wIDItem;        Menu or control id
  1170. //             WORD          wNotifyCode;    notification message
  1171. //
  1172. // Returns:    LONG   generally 0L
  1173. // --------------------------------------------------------------------
  1174. static LONG NEAR PlayerMovieCommands
  1175.                   ( HWND hwndMovie, WPARAM wIDItem, WORD wNotifyCode )
  1176.  
  1177. {
  1178.     NPMOVIEDATA   pMovieData;         // -> movie data struct
  1179.     DLGPROC       lpDlgProc;          // -> info dialog proc function
  1180.     HWND          hwndInfoDialog;     // HWND of info dialog box
  1181.     TimeRecord    trPosterTime;       // Poster time
  1182.     BOOL          bPlaySelectionOnly; // Flag
  1183.     char          szFormat[80];
  1184.     char          szTitle[80];
  1185.  
  1186.  
  1187.     if( !(pMovieData = (NPMOVIEDATA) GetWindowWord( hwndMovie, 0 ))) {
  1188.         CommonTellUser( PlayerQueryResources(),
  1189.             PLAYER_STRING_NOMOVIEDATA, PLAYER_STRING_CAPTION, MB_OK );
  1190.         return 0L;
  1191.     }
  1192.  
  1193.     switch( wIDItem ) {
  1194.         case PLAYER_MOVIE_SEARCH:
  1195.             if( pMovieData->hwndSearch )
  1196.                 SetFocus( pMovieData->hwndSearch );
  1197.             else {
  1198.                 pMovieData->tvSearch = 0;
  1199.                 pMovieData->lOffset = 0;
  1200.                 memset (&pMovieData->fr, 0, sizeof (FINDREPLACE));
  1201.                 pMovieData->fr.lStructSize = sizeof (FINDREPLACE);
  1202.                 pMovieData->fr.hwndOwner = hwndMovie;
  1203.                 pMovieData->fr.Flags = FR_DOWN | FR_HIDEWHOLEWORD;
  1204.                 pMovieData->fr.lpstrFindWhat = pMovieData->szSearch;
  1205.                 pMovieData->fr.wFindWhatLen = sizeof (pMovieData->szSearch);
  1206.                 pMovieData->hwndSearch = FindText (&pMovieData->fr);
  1207.                 PlayerSetActiveModeless (WA_ACTIVE, pMovieData->hwndSearch);
  1208.                 LoadString (PlayerQueryResources(), PLAYER_STRING_SEARCHTITLE, szFormat, sizeof( szFormat ));
  1209.                 wsprintf (szTitle, szFormat, (LPSTR) pMovieData->szMovieName );
  1210.                 SetWindowText (pMovieData->hwndSearch, szTitle);
  1211.             }
  1212.             return 0L;
  1213.  
  1214.         case PLAYER_MOVIE_GETINFO:
  1215.             if( pMovieData->hwndGetInfo )
  1216.                 SetFocus( pMovieData->hwndGetInfo );
  1217.             else if( !(lpDlgProc = (DLGPROC) MakeProcInstance
  1218.                 ( (FARPROC) GetInfoDlgProc, PlayerQueryInstance())) ||
  1219.                 !(hwndInfoDialog =
  1220.                 CreateDialog( PlayerQueryResources(),
  1221.                 MAKEINTRESOURCE( PLAYER_DLG_GETINFO ),
  1222.                 PlayerQueryFrameWindow(), lpDlgProc ))) {
  1223.                 CommonTellUser( PlayerQueryResources(),
  1224.                     PLAYER_STRING_NOMEMORY, NULL, MB_OK );
  1225.             }
  1226.  
  1227.             return 0L;
  1228.  
  1229.         case PLAYER_MOVIE_STOPATEND:
  1230.             MCDoAction( pMovieData->mcMovieController,
  1231.                 mcActionSetLoopIsPalindrome, (LPVOID) FALSE );
  1232.             MCDoAction( pMovieData->mcMovieController,
  1233.                 mcActionSetLooping, (LPVOID) FALSE );
  1234.             return 0L;
  1235.  
  1236.         case PLAYER_MOVIE_LOOP:
  1237.             MCDoAction( pMovieData->mcMovieController,
  1238.                 mcActionSetLooping, (LPVOID) TRUE );
  1239.             MCDoAction( pMovieData->mcMovieController,
  1240.                 mcActionSetLoopIsPalindrome, (LPVOID) FALSE );
  1241.             return 0L;
  1242.  
  1243.         case PLAYER_MOVIE_BACKANDFORTH:
  1244.             MCDoAction( pMovieData->mcMovieController,
  1245.                 mcActionSetLooping, (LPVOID) TRUE );
  1246.             MCDoAction( pMovieData->mcMovieController,
  1247.                 mcActionSetLoopIsPalindrome, (LPVOID) TRUE );
  1248.             return 0L;
  1249.  
  1250.         case PLAYER_MOVIE_PLAYSELONLY:
  1251.             MCDoAction( pMovieData->mcMovieController,
  1252.                 mcActionGetPlaySelection,
  1253.                 (LPVOID) &bPlaySelectionOnly );
  1254.  
  1255.             MCDoAction( pMovieData->mcMovieController,
  1256.                 mcActionSetPlaySelection,
  1257.                 (LPVOID) !bPlaySelectionOnly );
  1258.             return 0L;
  1259.  
  1260.  
  1261.         // For next 3 cases, if window is maximized or minimized, we need to
  1262.         // restore before resizing so that Windows knows that the window is
  1263.         // no longer maximized or minimized
  1264.  
  1265.         case PLAYER_MOVIE_HALFSIZE:
  1266.             if( ( pMovieData->wMinMaxEtc == SIZE_MAXIMIZED ) ||
  1267.                 ( pMovieData->wMinMaxEtc == SIZE_MINIMIZED ))
  1268.                 ShowWindow( hwndMovie, SW_SHOWNORMAL );
  1269.  
  1270.             return ResizeMovieAndWindow( hwndMovie, TRUE, pMovieData,
  1271.                 pMovieData->cx / 2,
  1272.                 pMovieData->cy / 2 );
  1273.  
  1274.         case PLAYER_MOVIE_NORMALSIZE:
  1275.             if( ( pMovieData->wMinMaxEtc == SIZE_MAXIMIZED ) ||
  1276.                 ( pMovieData->wMinMaxEtc == SIZE_MINIMIZED ))
  1277.                 ShowWindow( hwndMovie, SW_SHOWNORMAL );
  1278.  
  1279.             return ResizeMovieAndWindow( hwndMovie, TRUE, pMovieData,
  1280.                 pMovieData->cx,
  1281.                 pMovieData->cy );
  1282.  
  1283.         case PLAYER_MOVIE_DOUBLESIZE:
  1284.             if( ( pMovieData->wMinMaxEtc == SIZE_MAXIMIZED ) ||
  1285.                 ( pMovieData->wMinMaxEtc == SIZE_MINIMIZED ))
  1286.                 ShowWindow( hwndMovie, SW_SHOWNORMAL );
  1287.  
  1288.             return ResizeMovieAndWindow( hwndMovie, TRUE, pMovieData,
  1289.                 pMovieData->cx * 2,
  1290.                 pMovieData->cy * 2 );
  1291.  
  1292.         case PLAYER_MOVIE_SHOWPOSTER:
  1293.             trPosterTime.value.dwHi = 0L;
  1294.             trPosterTime.value.dwLo =
  1295.                 GetMoviePosterTime( pMovieData->mMovie );
  1296.             trPosterTime.scale = GetMovieTimeScale( pMovieData->mMovie );
  1297.             trPosterTime.base  = TIMEBASE_DEFAULT;
  1298.  
  1299.             // Stop the movie
  1300.             MCDoAction( pMovieData->mcMovieController,
  1301.                 mcActionPlay, (LPVOID) 0 );
  1302.             // Go to poster time
  1303.             MCDoAction( pMovieData->mcMovieController,
  1304.                 mcActionGoToTime, (LPVOID) &trPosterTime );
  1305.             return 0L;
  1306.     }
  1307.  
  1308.     return 0L; // should never get here
  1309.  
  1310. }
  1311.  
  1312. //// the following are some utility routines
  1313.  
  1314. // Function: ActivateTheController - Activates or deactivates the movie
  1315. //                                   controller
  1316. // --------------------------------------------------------------------
  1317. // Parameters: HWND         hwndMovie       Handle of movie window
  1318. //             NPMOVIEDATA  pMovieData      -> to movie data struct
  1319. //             BOOL         bActivate       Activate flag
  1320. //
  1321. // Returns:    VOID
  1322. // --------------------------------------------------------------------
  1323. static VOID NEAR ActivateTheController
  1324.              ( HWND hwndMovie, NPMOVIEDATA pMovieData, BOOL bActivate )
  1325.  
  1326. {
  1327.     short          nVol; // Sound volume
  1328.  
  1329.     if( bActivate && ( hwndMovie != (HWND) SendMessage
  1330.         ( PlayerQueryClientWindow(), WM_MDIGETACTIVE, 0, 0L )))
  1331.         return;
  1332.  
  1333.     MCActivate( pMovieData->mcMovieController, hwndMovie, bActivate );
  1334.  
  1335.     MCDoAction( pMovieData->mcMovieController,
  1336.         mcActionSetKeysEnabled, (LPVOID) bActivate );
  1337.     if( bActivate ) // RealizePalette only if activating
  1338.     {
  1339.         MCDoAction( pMovieData->mcMovieController,
  1340.             mcActionSetFlags, (LPVOID) mcFlagsUseWindowPalette );
  1341.         // InvalidateRect is needed to cause repainting in certain
  1342.         // situations when the window is iconic
  1343.         InvalidateRect( hwndMovie, NULL, TRUE );
  1344.     }
  1345.  
  1346.     MCDoAction( pMovieData->mcMovieController,
  1347.         mcActionGetVolume, (LPVOID) &nVol );
  1348.     if( ( bActivate && ( nVol < 0 )) || ( !bActivate && ( nVol > 0 )))
  1349.         MCDoAction( pMovieData->mcMovieController,
  1350.         mcActionSetVolume, (LPVOID) -nVol );
  1351. }
  1352.  
  1353.  
  1354.  
  1355. // Function: StartTheMovie - Starts the movie
  1356. // --------------------------------------------------------------------
  1357. // Parameters: NPMOVIEDATA  pMovieData      -> movie data struct
  1358. //
  1359. // Returns:    LONG         always 0L
  1360. // --------------------------------------------------------------------
  1361. static LONG NEAR StartTheMovie( NPMOVIEDATA pMovieData )
  1362.  
  1363. { // Reactivate the movie
  1364.     SetMovieActive( pMovieData->mMovie, TRUE );
  1365.   // Restart the movie if it was playing
  1366.     if( pMovieData->lfxSavePlayRate )
  1367.         MCDoAction( pMovieData->mcMovieController,
  1368.         mcActionPlay, (LPVOID) pMovieData->lfxSavePlayRate );
  1369.  
  1370.     return 0L;
  1371. }
  1372.  
  1373. // Function: StopTheMovie - Stops the movie
  1374. // --------------------------------------------------------------------
  1375. // Parameters: NPMOVIEDATA  pMovieData      -> movie data struct
  1376. //
  1377. // Returns:    LONG         always 0L
  1378. // --------------------------------------------------------------------
  1379. static LONG NEAR StopTheMovie( NPMOVIEDATA pMovieData )
  1380.  
  1381. { // save the play rate
  1382.     MCDoAction( pMovieData->mcMovieController,
  1383.         mcActionGetPlayRate, (LPVOID) &pMovieData->lfxSavePlayRate );
  1384.   // Stop the movie
  1385.     MCDoAction( pMovieData->mcMovieController,
  1386.         mcActionPlay, (LPVOID) 0 );
  1387.   // Deactivate movie to prevent painting over the icon
  1388.     SetMovieActive( pMovieData->mMovie, FALSE );
  1389.  
  1390.     return 0L;
  1391. }
  1392.  
  1393.  
  1394. // Function: PaintTheIcon - processes the WM_PAINT message when iconic
  1395. // --------------------------------------------------------------------
  1396. // Parameters: HWND         hwndPicture     Handle of Picture window
  1397. //             NPMOVIEDATA  pMovieData      -> movie data struct
  1398. //
  1399. // Returns:    LONG         0L
  1400. // --------------------------------------------------------------------
  1401. static LONG NEAR PaintTheIcon( HWND hwndMovie, NPMOVIEDATA pMovieData )
  1402.  
  1403. {
  1404.     HCURSOR          hcursorSave;   // Saved cursor
  1405.     HBRUSH           hbrush;        // Temp background brush
  1406.     PicHandle        phPoster;      // Pic handle
  1407.     PAINTSTRUCT      ps;            // Paint struct
  1408.     RECT             rcPicRect;     // Proportional pic rect
  1409.     WORD             wIconWidth;    // Icon width
  1410.     WORD             wIconHeight;   // Icon height
  1411.     WORD             wProportional; // Temp
  1412.  
  1413.     static RECT      rcIcon = {
  1414.                          2, 2, 34, 34}; // Rect used in painting icon
  1415.  
  1416.     // Make sure the entire window rect is invalidated
  1417.     InvalidateRect( hwndMovie, NULL, FALSE );
  1418.  
  1419.     if( !BeginPaint( hwndMovie, &ps ))
  1420.         return 0L;
  1421.  
  1422.     if( !pMovieData->mMovie ) {
  1423.         EndPaint( hwndMovie, &ps );
  1424.         return 0L;
  1425.     }
  1426.  
  1427.     hcursorSave = SetCursor( LoadCursor( NULL, IDC_WAIT ));
  1428.  
  1429.     if( pMovieData->bSoundOnly ) { // Erase the entire background since there is no picture
  1430.         if( hbrush = CreateSolidBrush( GetSysColor( COLOR_APPWORKSPACE ))) {
  1431.             FillRect( ps.hdc, &ps.rcPaint, hbrush );
  1432.             DeleteObject( hbrush );
  1433.         }
  1434.         // Now draw the film strip icon
  1435.         if( g.hmovieIcon )
  1436.             DrawIcon( ps.hdc, 2, 2, g.hmovieIcon );
  1437.     }
  1438.     else {
  1439.         if( phPoster = GetMoviePosterPict( pMovieData->mMovie )) {
  1440.             rcPicRect = rcIcon;
  1441.             wIconWidth  = rcIcon.right - rcIcon.left;
  1442.             wIconHeight = rcIcon.bottom - rcIcon.top;
  1443.             if( pMovieData->cx >
  1444.                 pMovieData->cy ) {
  1445.                 wProportional = MulDiv( wIconHeight,
  1446.                     pMovieData->cx,
  1447.                     pMovieData->cy );
  1448.                 rcPicRect.left  -= ( wProportional - wIconWidth ) / 2;
  1449.                 rcPicRect.right = rcPicRect.left + wProportional;
  1450.             }
  1451.             else if( pMovieData->cx <
  1452.                 pMovieData->cy ) {
  1453.                 wProportional = MulDiv( wIconWidth,
  1454.                     pMovieData->cy,
  1455.                     pMovieData->cx );
  1456.                 rcPicRect.top  -= ( wProportional - wIconHeight ) / 2;
  1457.                 rcPicRect.bottom = rcPicRect.top + wProportional;
  1458.             }
  1459.  
  1460.             // Draw the poster frame
  1461.             if( DrawPicture( ps.hdc, phPoster, &rcPicRect, NULL )) {
  1462.                 CommonTellUser( PlayerQueryResources(),
  1463.                     PLAYER_STRING_DRAWPICFAILED,
  1464.                     PLAYER_STRING_CAPTION, MB_OK );
  1465.  
  1466.                 // Validate rect to prevent infinite loop
  1467.                 ValidateRect( hwndMovie, NULL );
  1468.                 DisposePicture( phPoster );
  1469.                 SetCursor( hcursorSave );
  1470.                 EndPaint( hwndMovie, &ps );
  1471.                 return 0L;
  1472.             }
  1473.             else {
  1474.                 DisposePicture( phPoster );
  1475.             }
  1476.         }
  1477.  
  1478.         // Now draw the film strip icon
  1479.         if( g.hmovieIcon )
  1480.             DrawIcon( ps.hdc, 2, 2, g.hmovieIcon );
  1481.  
  1482.         // Now paint background
  1483.         ExcludeClipRect( ps.hdc, rcIcon.left, rcIcon.top,
  1484.             rcIcon.right, rcIcon.bottom );
  1485.         // COLOR_APPWORKSPACE is standard MDI background color
  1486.         if( hbrush = CreateSolidBrush( GetSysColor( COLOR_APPWORKSPACE ))) {
  1487.             FillRect( ps.hdc, &ps.rcPaint, hbrush );
  1488.             DeleteObject( hbrush );
  1489.         }
  1490.     }
  1491.  
  1492.     SetCursor( hcursorSave );
  1493.     EndPaint( hwndMovie, &ps );
  1494.  
  1495.     return 0L;
  1496.  
  1497. }
  1498.  
  1499.  
  1500. // Function: PrintFrame - prints indicated number of copies of
  1501. //                        the selected frame at normal size
  1502. // --------------------------------------------------------------------
  1503. // Parameters: HWND         hwndMovie       Handle of movie window
  1504. //             LPPRINTDLG   lppd            -> to PRINTDLG struct created
  1505. //                                          print common dialog
  1506. //
  1507. // Returns:    LONG         0L if successful
  1508. // --------------------------------------------------------------------
  1509. static LONG NEAR PrintFrame( HWND hwndMovie, LPPRINTDLG lppd )
  1510.  
  1511. {
  1512.     NPMOVIEDATA     pMovieData;  // -> movie data struct
  1513.     WORD            i;           // Counter
  1514.     DOCINFO         diDocInfo;   // Document info struct
  1515.     PicHandle       phFrame;     // Pichandle of current frame
  1516.     BOOL            bError;      // Error flag
  1517.     int             nError;      // Error return
  1518.     OSErr           oserr;       // Error return from DrawPicture
  1519.     int             xRes;        // Horz printer resolution
  1520.     int             yRes;        // Vert printer resolution
  1521.     int             xOffset;     // Horz offset to center picture
  1522.     int             yOffset;     // Vert offset to center picture
  1523.     RECT            rcFrame;     // Frame rect
  1524.     WORD            wWidthPage;  // Width of printed page in pixels
  1525.     WORD            wHeightPage; // Height of printed page in pixels
  1526.     TimeRecord      trMovieTime; // Temp time record
  1527.  
  1528.  
  1529.     if( !(pMovieData = (NPMOVIEDATA) GetWindowWord( hwndMovie, 0 ))) {
  1530.         CommonTellUser( PlayerQueryResources(),
  1531.             PLAYER_STRING_NOMOVIEDATA, PLAYER_STRING_CAPTION, MB_OK );
  1532.         // Turn off not reported flag
  1533.         return SP_ERROR &  ~SP_NOTREPORTED;
  1534.     }
  1535.  
  1536.     diDocInfo.cbSize      = sizeof( DOCINFO );
  1537.     diDocInfo.lpszDocName = pMovieData->szMovieName;
  1538.     diDocInfo.lpszOutput  = (LPSTR) NULL;
  1539.  
  1540.     if( !(phFrame = GetMoviePict( pMovieData->mMovie,
  1541.         GetMovieTime( pMovieData->mMovie, &trMovieTime )))) {
  1542.         CommonTellUser( PlayerQueryResources(),
  1543.             PLAYER_STRING_GETPICTFAILED, PLAYER_STRING_CAPTION, MB_OK );
  1544.         // Turn off not reported flag
  1545.         return SP_ERROR &  ~SP_NOTREPORTED;
  1546.     }
  1547.  
  1548.     wWidthPage  = GetDeviceCaps( lppd->hDC, HORZRES );
  1549.     wHeightPage = GetDeviceCaps( lppd->hDC, VERTRES );
  1550.  
  1551.     xRes = MulDiv( wWidthPage, 254,
  1552.         GetDeviceCaps( lppd->hDC, HORZSIZE ) * 10 );
  1553.     yRes = MulDiv( wHeightPage, 254,
  1554.         GetDeviceCaps( lppd->hDC, VERTSIZE ) * 10 );
  1555.     rcFrame.right  = MulDiv( pMovieData->cx,
  1556.         xRes, HIWORD( pMovieData->idMovieInfo.hRes ));
  1557.     rcFrame.bottom = MulDiv( pMovieData->cy,
  1558.         yRes, HIWORD( pMovieData->idMovieInfo.vRes ));
  1559.     rcFrame.left = rcFrame.top = 0;
  1560.  
  1561.     // Now make sure that frame fits on page
  1562.     if( rcFrame.right > (int) wWidthPage ) {
  1563.         rcFrame.bottom = MulDiv( rcFrame.bottom,
  1564.             wWidthPage, rcFrame.right );
  1565.         rcFrame.right = wWidthPage;
  1566.     }
  1567.     if( rcFrame.bottom > (int) wHeightPage ) {
  1568.         rcFrame.right = MulDiv( rcFrame.right,
  1569.             wHeightPage, rcFrame.bottom );
  1570.         rcFrame.bottom = wHeightPage;
  1571.     }
  1572.  
  1573.     // Now center rect on page
  1574.     xOffset = (wWidthPage  - rcFrame.right ) / 2;
  1575.     yOffset = (wHeightPage - rcFrame.bottom ) / 2;
  1576.     OffsetRect( &rcFrame, xOffset, yOffset );
  1577.  
  1578.     bError = FALSE;
  1579.     oserr  = 0L;
  1580.     nError = SP_ERROR;
  1581.  
  1582.     if( StartDoc( lppd->hDC, &diDocInfo ) > 0 ) {
  1583.         for( i=0; (i < lppd->nCopies) && !bError; i++ ) {
  1584.             if( StartPage( lppd->hDC ) > 0) {
  1585.                 if( (oserr = DrawPicture
  1586.                     ( lppd->hDC, phFrame, &rcFrame, NULL )) != 0L ) {
  1587.                     AbortDoc( lppd->hDC );
  1588.                     bError = TRUE;
  1589.                 }
  1590.                 else if( (nError = EndPage( lppd->hDC )) < 0 )
  1591.                     bError = TRUE;
  1592.             }
  1593.             else
  1594.                 bError = TRUE;
  1595.         }
  1596.     }
  1597.     else
  1598.         bError = TRUE;
  1599.  
  1600.     if( !bError )
  1601.         EndDoc( lppd->hDC );
  1602.  
  1603.     if( phFrame )
  1604.         DisposePicture( phFrame );
  1605.  
  1606.     return (LONG) nError;
  1607. }
  1608.  
  1609.  
  1610. // Function: SetMinMaxInfo - Processes the WM_GETMINMAXINFO message
  1611. // --------------------------------------------------------------------
  1612. // Parameters: HWND               hwndMovie     Handle of movie wnd
  1613. //             NPMOVIEDATA        pMovieData    -> to movie data
  1614. //             MINMAXINFO FAR*    lpmmi         -> to minmaxinfo struct
  1615. //
  1616. // Returns:    LONG               always 0L
  1617. // --------------------------------------------------------------------
  1618. static LONG NEAR SetMinMaxInfo
  1619.       ( HWND hwndMovie, NPMOVIEDATA pMovieData, MINMAXINFO FAR* lpmmi )
  1620.  
  1621. {
  1622.     RECT   rcWindow; // Movie window rect
  1623.  
  1624.     if( PlayerQueryMDIAction() == PLAYER_WINDOW_CASCADE ) {
  1625.         GetWindowRect( hwndMovie, &rcWindow );
  1626.         lpmmi->ptMaxTrackSize.x = rcWindow.right - rcWindow.left;
  1627.         lpmmi->ptMaxTrackSize.y = rcWindow.bottom - rcWindow.top;
  1628.         lpmmi->ptMinTrackSize = lpmmi->ptMaxTrackSize;
  1629.         lpmmi->ptMaxSize      = lpmmi->ptMaxTrackSize;
  1630.     }
  1631.     else {
  1632.         lpmmi->ptMinTrackSize.x = 3 * GetSystemMetrics( SM_CXSIZE );
  1633.         lpmmi->ptMinTrackSize.y = GetSystemMetrics( SM_CYCAPTION ) +
  1634.             g.wMovieControllerHeight +
  1635.             2 * GetSystemMetrics( SM_CYFRAME );
  1636.         // Disable vertical resizing if sound only movie
  1637.         if( pMovieData && pMovieData->bSoundOnly ) {
  1638.             lpmmi->ptMinTrackSize.y -= 2;
  1639.             lpmmi->ptMaxTrackSize.y = lpmmi->ptMinTrackSize.y;
  1640.         }
  1641.     }
  1642.  
  1643.     return 0L;
  1644. }
  1645.  
  1646.  
  1647. // Function: GetInfoDlgProc - Get Info dialog proc
  1648. // --------------------------------------------------------------------
  1649. // Parameters: As required by Microsoft Windows
  1650. //
  1651. // Returns:    As required by Microsoft Windows
  1652. // --------------------------------------------------------------------
  1653. BOOL __export CALLBACK GetInfoDlgProc
  1654.     ( HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam )
  1655.  
  1656. {
  1657.     NPMOVIEDATA   pMovieData; // -> movie data struct
  1658.     HWND          hwndMovie;  // HWND of movie window
  1659.     HWND          hwndCtl;    // Handle of control
  1660.     HDC           hdc;        // DC of dialog
  1661.     int           nHeight;    // Height of control text font
  1662.  
  1663.     switch( message ) {
  1664.         case WM_INITDIALOG:
  1665.             hwndMovie = (HWND) SendMessage
  1666.                 ( PlayerQueryClientWindow(), WM_MDIGETACTIVE, 0, 0L );
  1667.  
  1668.             // Use property to associate movie window handle with
  1669.             // info dialog. This is necessary because MDI makes frame
  1670.             // window the parent of all dialogs no matter what handle
  1671.             // is used in the CreateDialog call
  1672.             SetProp( hdlg, GETINFOMOVIEPROP, (HANDLE) hwndMovie );
  1673.  
  1674.             if( pMovieData = (NPMOVIEDATA) GetWindowWord( hwndMovie, 0 )) {
  1675.                 pMovieData->hwndGetInfo = hdlg;
  1676.                 // Cache selection strings to speed up updates
  1677.                 if( !g.szSelectFormat[0] )
  1678.                     LoadString( PlayerQueryResources(),
  1679.                     PLAYER_STRING_SELECTION,
  1680.                     g.szSelectFormat, sizeof( g.szSelectFormat ));
  1681.                 if( !g.szNoSelection[0] )
  1682.                     LoadString( PlayerQueryResources(),
  1683.                     PLAYER_STRING_NOSELECTION,
  1684.                     g.szNoSelection, sizeof( g.szNoSelection ));
  1685.  
  1686.                 if( hdc = GetDC( hdlg )) {
  1687.                     nHeight = -MulDiv( 8, GetDeviceCaps( hdc, LOGPIXELSY ), 72 );
  1688.                     if( pMovieData->hfInfo = MakeAnArialFont( hdc, nHeight )) {
  1689.                         hwndCtl = GetWindow( hdlg, GW_CHILD );
  1690.                         while( hwndCtl ) {
  1691.                             if( GetDlgCtrlID( hwndCtl ) != IDOK )
  1692.                                 SendMessage( hwndCtl, WM_SETFONT,
  1693.                                 (WPARAM) pMovieData->hfInfo, 0 );
  1694.                             hwndCtl = GetWindow( hwndCtl, GW_HWNDNEXT );
  1695.                         }
  1696.                     }
  1697.                     ReleaseDC( hdlg, hdc );
  1698.                 }
  1699.  
  1700.                 FillMovieInfo( hdlg, pMovieData );
  1701.             }
  1702.  
  1703.             return TRUE;
  1704.  
  1705.         case WM_ACTIVATE:
  1706.             PlayerSetActiveModeless( wParam, hdlg );
  1707.             return TRUE;
  1708.  
  1709.         // WM_USER messages
  1710.  
  1711.         case WM_PLAYER_INFO_UPDATEFILENAME:
  1712.             hwndMovie = (HWND) GetProp( hdlg, GETINFOMOVIEPROP );
  1713.             if( IsWindow( hwndMovie ) && ( pMovieData =
  1714.                 (NPMOVIEDATA) GetWindowWord( hwndMovie, 0 )))
  1715.                 UpdateInfoFileName( pMovieData );
  1716.             break;
  1717.  
  1718.         case WM_PLAYER_INFO_UPDATE:
  1719.             hwndMovie = (HWND) GetProp( hdlg, GETINFOMOVIEPROP );
  1720.             if( IsWindow( hwndMovie ) && ( pMovieData =
  1721.                 (NPMOVIEDATA) GetWindowWord( hwndMovie, 0 )))
  1722.                 FillMovieInfo( hdlg, pMovieData );
  1723.             break;
  1724.  
  1725.         // End WM_USER messages
  1726.  
  1727.         case WM_COMMAND:
  1728.             return DestroyWindow( hdlg );
  1729.  
  1730.         case WM_DESTROY:
  1731.             hwndMovie = (HWND) GetProp( hdlg, GETINFOMOVIEPROP );
  1732.             if( IsWindow( hwndMovie ) && ( pMovieData =
  1733.                 (NPMOVIEDATA) GetWindowWord( hwndMovie, 0 ))) {
  1734.                 pMovieData->hwndGetInfo = NULL;
  1735.  
  1736.                 if( pMovieData->hfInfo )
  1737.                     DeleteObject( pMovieData->hfInfo );
  1738.                 pMovieData->hfInfo = NULL;
  1739.             }
  1740.  
  1741.             RemoveProp( hdlg, GETINFOMOVIEPROP );
  1742.             break;
  1743.     }
  1744.  
  1745.     return FALSE;
  1746.  
  1747. }
  1748.  
  1749.  
  1750. // Function: FillMovieInfo - Fills dialog controls with movie data
  1751. // --------------------------------------------------------------------
  1752. // Parameters: HWND          hdlg            Handle of dialog wnd
  1753. //             NPMOVIEDATA   pMovieData      -> movie data struct
  1754. //
  1755. // Returns:    VOID
  1756. // --------------------------------------------------------------------
  1757. static VOID NEAR FillMovieInfo( HWND hdlg, NPMOVIEDATA pMovieData )
  1758.  
  1759. {
  1760.     char           szBuffer[MAX_PATH_LEN];          // Buffer
  1761.     char           szFormat[30];                    // Format buffer
  1762.     TimeValue      tvDuration;                      // Duration of movie
  1763.     double         fTimeScale;                      // Timescale
  1764.     RECT           rcMovie;                         // Current movie rect
  1765.     DWORD          dwColors;                        // Number of colors
  1766.     char           szCompressor[sizeof(DWORD) + 1]; // compressor type
  1767.     WORD           wIDString;                       // Colors string id
  1768.     DWORD          dwRate;                          // Sound sample rate
  1769.     DWORD          dwKRate;                         // Sound sample rate
  1770.     char           szNull[] = "";                   // Static null string
  1771.  
  1772.     g.bUpdatingInfo = TRUE;
  1773.  
  1774.     // Movie name: Append duplication index if > 0
  1775.     UpdateInfoFileName( pMovieData );
  1776.  
  1777.     // file size
  1778.     SetDlgItemText( hdlg, MOVIE_INFO_FILESIZE, pMovieData->szFileSize );
  1779.  
  1780.     // Get movie time scale
  1781.     if( ( fTimeScale = (double)
  1782.         GetMovieTimeScale( pMovieData->mMovie )) != 0. ) { // Do these only if timescale != zero to avoid divide by 0
  1783.                                                            // Movie duration
  1784.         tvDuration = GetMovieDuration( pMovieData->mMovie );
  1785.         LoadString( PlayerQueryResources(), PLAYER_STRING_DURATION,
  1786.             szFormat, sizeof( szFormat ));
  1787.         sprintf( szBuffer, szFormat, tvDuration / fTimeScale );
  1788.         SetDlgItemText( hdlg, MOVIE_INFO_DURATION, szBuffer );
  1789.  
  1790.         // Current selection
  1791.         DisplayCurrentSelection( pMovieData );
  1792.     }
  1793.  
  1794.     if( !pMovieData->bSoundOnly ) {
  1795.  
  1796.         // temp hack
  1797.         #ifdef done          
  1798.         if (pMovieData->oserrVideoInfo != noErr) {
  1799.             if (pMovieData->oserrMPEGInfo != noErr) {
  1800.                 if (pMovieData->oserrTextInfo != noErr) {
  1801.                 /* oops! */
  1802.                 }
  1803.                 else pMovieData->idMovieInfo = pMovieData->idTextInfo;
  1804.             }
  1805.             else pMovieData->idMovieInfo = pMovieData->idMPEGInfo;
  1806.         }
  1807.         #endif
  1808.  
  1809.         LoadString( PlayerQueryResources(), PLAYER_STRING_WANDH,
  1810.             szFormat, sizeof( szFormat ));
  1811.         GetMovieBox( pMovieData->mMovie, &rcMovie );
  1812.  
  1813.         wsprintf( szBuffer, szFormat, rcMovie.right - rcMovie.left,
  1814.             rcMovie.bottom - rcMovie.top );
  1815.         SetDlgItemText( hdlg, MOVIE_INFO_CURSIZE, szBuffer );
  1816.  
  1817.         // Normal Width and Height
  1818.         wsprintf( szBuffer, szFormat,
  1819.             pMovieData->cx,
  1820.             pMovieData->cy );
  1821.         SetDlgItemText( hdlg, MOVIE_INFO_WANDH, szBuffer );
  1822.         wsprintf( szBuffer, szFormat, pMovieData->cy );
  1823.  
  1824.         // Resolution
  1825.         if( HIWORD( pMovieData->idMovieInfo.hRes ) != 0 ) {
  1826.             LoadString( PlayerQueryResources(),
  1827.                 PLAYER_STRING_RESOLUTION, szFormat, sizeof( szFormat ));
  1828.             wsprintf( szBuffer, szFormat,
  1829.                 HIWORD( pMovieData->idMovieInfo.hRes ));
  1830.         }
  1831.         else {
  1832.             LoadString( PlayerQueryResources(),
  1833.                 PLAYER_STRING_NORESOLUTION, szBuffer, sizeof( szBuffer ));
  1834.         }
  1835.         SetDlgItemText( hdlg, MOVIE_INFO_RESOLUTION, szBuffer );
  1836.  
  1837.  
  1838.         // Normal colors
  1839.         switch( pMovieData->idMovieInfo.depth ) {
  1840.             case 1:      // Black and White
  1841.                 wIDString = PLAYER_STRING_CLRS_BANDW;      
  1842.                 break;
  1843.             case 1 + 32: // 2 Grays
  1844.                 wIDString = PLAYER_STRING_CLRS_2GRAYS;     
  1845.                 break;
  1846.             case 2:      // 4 Colors
  1847.                 wIDString = PLAYER_STRING_CLRS_4COLORS;    
  1848.                 break;
  1849.             case 2 + 32: // 4 Grays
  1850.                 wIDString = PLAYER_STRING_CLRS_4GRAYS;     
  1851.                 break;
  1852.             case 4:      // 16 Colors
  1853.                 wIDString = PLAYER_STRING_CLRS_16COLORS;   
  1854.                 break;
  1855.             case 4 + 32: // 16 Grays
  1856.                 wIDString = PLAYER_STRING_CLRS_16GRAYS;    
  1857.                 break;
  1858.             case 8:      // 256 Colors
  1859.                 wIDString = PLAYER_STRING_CLRS_256COLORS;  
  1860.                 break;
  1861.             case 8 + 32: // 256 Grays
  1862.                 wIDString = PLAYER_STRING_CLRS_256GRAYS;   
  1863.                 break;
  1864.             case 16:     // Thousands of Colors
  1865.                 wIDString = PLAYER_STRING_CLRS_THOUSANDS;  
  1866.                 break;
  1867.             case 24:     // Millions of Colors
  1868.                 wIDString = PLAYER_STRING_CLRS_MILLIONS;   
  1869.                 break;
  1870.             case 32:     // Millions of Colors+
  1871.                 wIDString = PLAYER_STRING_CLRS_MILLNSPLUS; 
  1872.                 break;
  1873.             default:
  1874.                 wIDString = 0xffff;
  1875.                 if( pMovieData->idMovieInfo.depth < 32 ) {
  1876.                     LoadString( PlayerQueryResources(), PLAYER_STRING_COLORS,
  1877.                         szFormat, sizeof( szFormat ));
  1878.                     dwColors = 1L << pMovieData->idMovieInfo.depth;
  1879.                     wsprintf( szBuffer, szFormat, dwColors );
  1880.                 }
  1881.                 else {
  1882.                     szBuffer[0] = '\0';
  1883.                 }
  1884.                 break;
  1885.         }
  1886.         if( wIDString != 0xffff )
  1887.             LoadString( PlayerQueryResources(), wIDString,
  1888.             szBuffer, sizeof( szBuffer ));
  1889.         SetDlgItemText( hdlg, MOVIE_INFO_COLORS, szBuffer );
  1890.  
  1891.         // Compressor type. Use .name if not empty
  1892.         if( pMovieData->idMovieInfo.name[0] ) {
  1893.             SetDlgItemText( hdlg, MOVIE_INFO_COMPRESSOR,
  1894.                 pMovieData->idMovieInfo.name );
  1895.         }
  1896.         else // Check Codec type for 'raw'
  1897.         { // Compressor type is stored as a DWORD. i.e. 'jpeg'
  1898.           // Spaces in "raw ", "rle " etc are necessary !!!
  1899.             if( pMovieData->idMovieInfo.CodecType ) {
  1900.                 *((PDWORD) &szCompressor) = pMovieData->idMovieInfo.CodecType;
  1901.                 szCompressor[ sizeof(DWORD) ] = '\0';
  1902.             }
  1903.             szBuffer[0] = '\0';
  1904.             if( !pMovieData->idMovieInfo.CodecType ||
  1905.                 !lstrcmpi( szCompressor, "raw " ))
  1906.                 wIDString = PLAYER_STRING_CODEC_NONE;
  1907.             else if( !lstrcmpi( szCompressor, "jpeg" ))
  1908.                 wIDString = PLAYER_STRING_CODEC_PHOTO;
  1909.             else if( !lstrcmpi( szCompressor, "rle " ))
  1910.                 wIDString = PLAYER_STRING_CODEC_ANIMATION;
  1911.             else if( !lstrcmpi( szCompressor, "smc " ))
  1912.                 wIDString = PLAYER_STRING_CODEC_GRAPHICS;
  1913.             else if( !lstrcmpi( szCompressor, "rpza" ))
  1914.                 wIDString = PLAYER_STRING_CODEC_VIDEO;
  1915.             else if( !lstrcmpi( szCompressor, "cvid" ))
  1916.                 wIDString = PLAYER_STRING_CODEC_CVID;
  1917.             else
  1918.                 wIDString = PLAYER_STRING_CODEC_NONE;
  1919.  
  1920.             LoadString( PlayerQueryResources(), wIDString,
  1921.                 szBuffer, sizeof( szBuffer ));
  1922.  
  1923.             SetDlgItemText( hdlg, MOVIE_INFO_COMPRESSOR, szBuffer );
  1924.         }
  1925.     }
  1926.     else {
  1927.         LoadString( PlayerQueryResources(),
  1928.             PLAYER_STRING_NOVIDEO, szBuffer, sizeof( szBuffer ));
  1929.         SetDlgItemText( hdlg, MOVIE_INFO_CURSIZE,    szBuffer );
  1930.         SetDlgItemText( hdlg, MOVIE_INFO_WANDH,      szNull );
  1931.         SetDlgItemText( hdlg, MOVIE_INFO_RESOLUTION, szNull );
  1932.         SetDlgItemText( hdlg, MOVIE_INFO_COLORS,     szNull );
  1933.         SetDlgItemText( hdlg, MOVIE_INFO_COMPRESSOR, szNull );
  1934.     }
  1935.  
  1936.     // Sound info
  1937.     if( !GetMovieIndTrackType(pMovieData->mMovie,1,SoundMediaType,movieTrackMediaType)) {
  1938.         if ( GetMovieIndTrackType(pMovieData->mMovie,1,MusicMediaType,movieTrackMediaType)) {
  1939.             LoadString( PlayerQueryResources(),
  1940.                 PLAYER_STRING_SND_MIDISOUND, szBuffer, sizeof( szBuffer ));
  1941.             SetDlgItemText( hdlg, MOVIE_INFO_SND_NUMCHANNELS, szBuffer );
  1942.             SetDlgItemText( hdlg, MOVIE_INFO_SND_SOUNDQUALITY, szNull );
  1943.         }
  1944.         else if ( GetMovieIndTrackType(pMovieData->mMovie,1,MPEGMediaType,movieTrackMediaType)) {
  1945.             LoadString( PlayerQueryResources(),
  1946.                 PLAYER_STRING_SND_MPEGSOUND, szBuffer, sizeof( szBuffer ));
  1947.             SetDlgItemText( hdlg, MOVIE_INFO_SND_NUMCHANNELS, szBuffer );
  1948.             SetDlgItemText( hdlg, MOVIE_INFO_SND_SOUNDQUALITY, szNull );
  1949.         }
  1950.         else if( pMovieData->oserrSoundInfo == noSoundTrackInMovie ) {
  1951.             LoadString( PlayerQueryResources(),
  1952.                 PLAYER_STRING_SND_NOSOUND, szBuffer, sizeof( szBuffer ));
  1953.             SetDlgItemText( hdlg, MOVIE_INFO_SND_NUMCHANNELS, szBuffer );
  1954.             SetDlgItemText( hdlg, MOVIE_INFO_SND_SOUNDQUALITY, szNull );
  1955.         }
  1956.         else if( pMovieData->oserrSoundInfo == soundSupportNotAvailable ) {
  1957.             LoadString( PlayerQueryResources(),
  1958.                 PLAYER_STRING_SND_NOCARD, szBuffer, sizeof( szBuffer ));
  1959.             SetDlgItemText( hdlg, MOVIE_INFO_SND_NUMCHANNELS, szBuffer );
  1960.             SetDlgItemText( hdlg, MOVIE_INFO_SND_SOUNDQUALITY, szNull );
  1961.         }
  1962.     }
  1963.     else { // Num of channels
  1964.         if( pMovieData->sdSoundInfo.numChannels == 1 )
  1965.             LoadString( PlayerQueryResources(), PLAYER_STRING_SND_MONO,
  1966.             szBuffer, sizeof( szBuffer ));
  1967.         else
  1968.             LoadString( PlayerQueryResources(), PLAYER_STRING_SND_STEREO,
  1969.             szBuffer, sizeof( szBuffer ));
  1970.         SetDlgItemText( hdlg, MOVIE_INFO_SND_NUMCHANNELS, szBuffer );
  1971.  
  1972.         // Sample size and rate
  1973.         LoadString( PlayerQueryResources(),
  1974.             PLAYER_STRING_SND_SOUNDQUALITY, szFormat, sizeof( szFormat ));
  1975.         dwRate = ((DWORD) pMovieData->sdSoundInfo.sampleRate ) / 65536L;
  1976.         dwKRate = dwRate / 1000;
  1977.         dwRate -= dwKRate * 1000;
  1978.         wsprintf( szBuffer, szFormat,
  1979.             pMovieData->sdSoundInfo.sampleSize, dwKRate, dwRate );
  1980.         SetDlgItemText( hdlg, MOVIE_INFO_SND_SOUNDQUALITY, szBuffer );
  1981.     }
  1982.  
  1983.     // End sound info
  1984.  
  1985.     g.bUpdatingInfo = FALSE;
  1986.  
  1987.     return;
  1988. }
  1989.  
  1990.  
  1991. // Function: UpdateInfoFileName - Updates the file name with the current
  1992. //                                instance count in the info dialog
  1993. // --------------------- -----------------------------------------------
  1994. // Parameters: NPMOVIEDATA    pMovieData       -> to MOVIEDATA struct
  1995. //
  1996. // Returns:    VOID
  1997. // --------------------------------------------------------------------
  1998. static VOID NEAR UpdateInfoFileName( NPMOVIEDATA pMovieData )
  1999.  
  2000. {
  2001.     char      szBuffer[MAX_NAME_LEN + 10]; // Buffer
  2002.     char      szFormat[20];                // Format buffer
  2003.  
  2004.     lstrcpy( szFormat, "%s%s" );
  2005.     if( pMovieData->wDuplicationIndex > 0 )
  2006.         lstrcat( szFormat, ":%u" );
  2007.     wsprintf( szBuffer, szFormat, (LPSTR) pMovieData->szMovieName,
  2008.         (LPSTR) pMovieData->szMovieExt,
  2009.         pMovieData->wDuplicationIndex );
  2010.     AnsiUpper( szBuffer );
  2011.     SetDlgItemText( pMovieData-> hwndGetInfo,
  2012.         MOVIE_INFO_NAME, (LPSTR) szBuffer );
  2013.  
  2014.     return;
  2015. }
  2016.  
  2017.  
  2018. // Function:  DisplayCurrentSelection - Displays the current selection in
  2019. //                                      the info dialog
  2020. // --------------------------------------------------------------------
  2021. // Parameters: NPMOVIEDATA      pMovieData        -> movie data struct
  2022. //
  2023. // Returns:    VOID
  2024. // --------------------------------------------------------------------
  2025. static VOID NEAR DisplayCurrentSelection( NPMOVIEDATA pMovieData )
  2026.  
  2027. {
  2028.     char     szBuffer[100];   // Buffer
  2029.     double   fSelectionStart; // Beginning of selection
  2030.     double   fSelectionEnd;   // End of selection
  2031.     double   fTimeScale;      // Time scale of movie
  2032.  
  2033.     if( ( ( fTimeScale = (double)
  2034.         GetMovieTimeScale( pMovieData->mMovie )) != 0. ) &&
  2035.         ( pMovieData->trSelectionStart.value.dwLo != (DWORD) -1) &&
  2036.         ( pMovieData->trSelectionDuration.value.dwLo > 0L )) {
  2037.         fSelectionStart = pMovieData->trSelectionStart.value.dwLo /
  2038.             fTimeScale ;
  2039.         fSelectionEnd = fSelectionStart +
  2040.             pMovieData->trSelectionDuration.value.dwLo /
  2041.             fTimeScale ;
  2042.  
  2043.         sprintf( szBuffer, g.szSelectFormat, fSelectionStart, fSelectionEnd );
  2044.         SetDlgItemText( pMovieData-> hwndGetInfo,
  2045.             MOVIE_INFO_SELECTION, szBuffer );
  2046.     }
  2047.     else {
  2048.         SetDlgItemText( pMovieData-> hwndGetInfo,
  2049.             MOVIE_INFO_SELECTION, g.szNoSelection );
  2050.     }
  2051.  
  2052.     return;
  2053.  
  2054. }
  2055.  
  2056.  
  2057. // Function: ActionFilter - Used to filter the selection change message
  2058. // --------------------------------------------------------------------
  2059. // Parameters: MovieController  mcController      Movie controller
  2060. //             UNIT             psAction          action parameter
  2061. //             LPVOID           lpParm            DoAction parameter
  2062. //             LONG             lUserData         User defined data
  2063. //
  2064. // Returns:    BOOL             TRUE  if no further action
  2065. //                              FALSE if controller is to perform action
  2066. // --------------------------------------------------------------------
  2067. BOOL __export CALLBACK ActionFilter
  2068.     ( MovieController mcController, UINT psAction,
  2069.     LPVOID lpParm, LONG lUserData )
  2070.  
  2071. {
  2072.     NPMOVIEDATA         pMovieData; // -> movie data struct
  2073.  
  2074.     switch( psAction ) {
  2075.         case mcActionControllerSizeChanged:
  2076.             pMovieData = (NPMOVIEDATA) LOWORD( lUserData );
  2077.             if( !pMovieData->bSettingControllerSize ) {
  2078.                 ResizeMovieAndWindow( (HWND) HIWORD( lUserData ),
  2079.                     FALSE, pMovieData, 0, 0 );
  2080.                 if( pMovieData->hwndGetInfo && !g.bUpdatingInfo ) { // Need to post message here because FALSE second
  2081.                                                                     // parameter prevents ResizeMovie from being called
  2082.                                                                     // by ResizeMovieAndWindow.
  2083.                                                                     // WM_PLAYER_INFO_UPDATE is defined to be in
  2084.                                                                     // the range WM_COALESCE_FIRST to WM_COALESCE_LAST
  2085.                                                                     // which tells Windows to prevent duplicate messages
  2086.                                                                     // from appearing in the queue.
  2087.                     PostMessage( pMovieData->hwndGetInfo,
  2088.                         WM_PLAYER_INFO_UPDATE, 0, 0L );
  2089.                 }
  2090.             }
  2091.             else {
  2092.                 pMovieData->bSettingControllerSize = FALSE;
  2093.             }
  2094.  
  2095.             break;
  2096.  
  2097.         case mcActionSetSelectionBegin:
  2098.             pMovieData = (NPMOVIEDATA) LOWORD( lUserData );
  2099.             pMovieData->trSelectionStart = *( TimeRecord FAR *) lpParm;
  2100.  
  2101.             break;
  2102.  
  2103.         case mcActionSetSelectionDuration:
  2104.             pMovieData = (NPMOVIEDATA) LOWORD( lUserData );
  2105.             pMovieData->trSelectionDuration = *( TimeRecord FAR *) lpParm;
  2106.  
  2107.             if( pMovieData->hwndGetInfo )
  2108.                 DisplayCurrentSelection( pMovieData );
  2109.             break;
  2110.  
  2111.         default:
  2112.             break;
  2113.     }
  2114.  
  2115.     return FALSE;
  2116. }
  2117.  
  2118.  
  2119. // Function: InitializePopupMenus - Called just before the popup menus
  2120. //                                  are displayed
  2121. // --------------------------------------------------------------------
  2122. // Parameters: HWND         hwndMovie       Handle of movie window
  2123. //             HMENU        hmenuPopup      Handle of popup menu
  2124. //             int          nPopupIndex     Index of popup
  2125. //
  2126. // Returns:    LONG         0L if successful
  2127. // --------------------------------------------------------------------
  2128. static LONG NEAR InitializePopupMenus
  2129.                 ( HWND hwndMovie, HMENU hmenuPopup, int nPopupIndex )
  2130.  
  2131. {
  2132.     NPMOVIEDATA   pMovieData;         // -> movie data struct
  2133.     LONG          lControllerInfo;    // Controller info
  2134.     BOOL          bLooping;           // TRUE if looping
  2135.     BOOL          bPalindrome;        // TRUE if looping palindrome
  2136.     BOOL          bPlaySelectionOnly; // TRUE if playing selection only
  2137.     WORD          wSelectedSize;      // Nonzero if movie is a standard size
  2138.     RECT          rcMovie;            // Movie rect
  2139.     WORD          wMovieWidth;        // Width of movie
  2140.     WORD          wMovieHeight;       // Height of movie
  2141.     char          szTitle[64];        // OLE Client doc title
  2142.     char          szItemFormat1[32];  // Item format string
  2143.     char          szItem1[128];       // New item string
  2144.     char          szItemFormat2[32];  // Item format string
  2145.     char          szItem2[128];       // New item string
  2146.  
  2147.  
  2148.  
  2149.     if( !(pMovieData = (NPMOVIEDATA) GetWindowWord( hwndMovie, 0 ))) {
  2150.         CommonTellUser( PlayerQueryResources(),
  2151.             PLAYER_STRING_NOMOVIEDATA, PLAYER_STRING_CAPTION, MB_OK );
  2152.         return 0L;
  2153.     }
  2154.  
  2155.     MCGetControllerInfo( pMovieData->mcMovieController,
  2156.         &lControllerInfo );
  2157.  
  2158.     // Decrement index if maximized since MDI adds a system menu item
  2159.     // which puts count off by one
  2160.     if( IsZoomed( hwndMovie ))
  2161.         nPopupIndex--;
  2162.  
  2163.     if( nPopupIndex == MENU_FILE_POS ) { // See if wnd is an activated client object
  2164.         if( QTOLE_IsActiveObjectWnd
  2165.             ( PlayerQueryOleData(), hwndMovie, szTitle )) {
  2166.             LoadString( PlayerQueryResources(),
  2167.                 PLAYER_STRING_OLECLOSE, szItemFormat1, sizeof( szItemFormat1 ));
  2168.             wsprintf( szItem1, szItemFormat1, (LPSTR) szTitle );
  2169.  
  2170.             LoadString( PlayerQueryResources(),
  2171.                 PLAYER_STRING_OLEEXIT, szItemFormat2, sizeof( szItemFormat2 ));
  2172.             wsprintf( szItem2, szItemFormat2, (LPSTR) szTitle );
  2173.         }
  2174.         else {
  2175.             LoadString( PlayerQueryResources(),
  2176.                 PLAYER_STRING_CLOSE, szItem1, sizeof( szItem1 ));
  2177.             LoadString( PlayerQueryResources(),
  2178.                 PLAYER_STRING_EXIT, szItem2, sizeof( szItem2 ));
  2179.         }
  2180.  
  2181.         DeleteMenu( hmenuPopup, PLAYER_FILE_CLOSE, MF_BYCOMMAND );
  2182.         InsertMenu( hmenuPopup, 1, MF_BYPOSITION,
  2183.             PLAYER_FILE_CLOSE, szItem1 );
  2184.         DeleteMenu( hmenuPopup, PLAYER_FILE_EXIT, MF_BYCOMMAND );
  2185.         InsertMenu( hmenuPopup, (UINT) -1, MF_BYPOSITION,
  2186.             PLAYER_FILE_EXIT, szItem2 );
  2187.  
  2188.         EnableMenuItem( hmenuPopup, PLAYER_FILE_PRINT,
  2189.             ( pMovieData->bSoundOnly ||
  2190.             (lControllerInfo & mcInfoIsPlaying)) ? MF_GRAYED: MF_ENABLED );
  2191.         EnableMenuItem( hmenuPopup, PLAYER_FILE_PRTSETUP,
  2192.             pMovieData->bSoundOnly ? MF_GRAYED: MF_ENABLED );
  2193.     }
  2194.     else if( nPopupIndex == MENU_EDIT_POS ) {
  2195.         EnableMenuItem( hmenuPopup, PLAYER_EDIT_COPY,
  2196.             ( IsIconic( hwndMovie ) ||
  2197.             ( lControllerInfo & mcInfoIsPlaying )) ? MF_GRAYED: MF_ENABLED );
  2198.         EnableMenuItem( hmenuPopup, PLAYER_EDIT_OPTIONS,
  2199.             ( IsIconic( hwndMovie ) ||
  2200.             ( lControllerInfo & mcInfoIsPlaying )) ? MF_GRAYED: MF_ENABLED );
  2201.  
  2202.     }
  2203.     else if( nPopupIndex == MENU_MOVIE_POS ) {
  2204.         bLooping    = (( lControllerInfo & mcInfoIsLooping ) != 0L );
  2205.         bPalindrome = (( lControllerInfo & mcInfoIsInPalindrome ) != 0L );
  2206.  
  2207.         CheckMenuItem( hmenuPopup, PLAYER_MOVIE_STOPATEND,
  2208.             ( bLooping || bPalindrome ) ? MF_UNCHECKED: MF_CHECKED );
  2209.         CheckMenuItem( hmenuPopup, PLAYER_MOVIE_LOOP,
  2210.             ( bLooping && !bPalindrome ) ? MF_CHECKED: MF_UNCHECKED );
  2211.         CheckMenuItem( hmenuPopup, PLAYER_MOVIE_BACKANDFORTH,
  2212.             ( bLooping && bPalindrome ) ? MF_CHECKED: MF_UNCHECKED );
  2213.  
  2214.         // Toggle play selection only
  2215.         MCDoAction( pMovieData->mcMovieController,
  2216.             mcActionGetPlaySelection, (LPVOID) &bPlaySelectionOnly );
  2217.         CheckMenuItem( hmenuPopup, PLAYER_MOVIE_PLAYSELONLY,
  2218.             ( bPlaySelectionOnly ) ? MF_CHECKED: MF_UNCHECKED );
  2219.  
  2220.  
  2221.         EnableMenuItem( hmenuPopup, PLAYER_MOVIE_HALFSIZE,
  2222.             pMovieData->bSoundOnly ? MF_GRAYED: MF_ENABLED );
  2223.         EnableMenuItem( hmenuPopup, PLAYER_MOVIE_NORMALSIZE,
  2224.             pMovieData->bSoundOnly ? MF_GRAYED: MF_ENABLED );
  2225.         EnableMenuItem( hmenuPopup, PLAYER_MOVIE_DOUBLESIZE,
  2226.             pMovieData->bSoundOnly ? MF_GRAYED: MF_ENABLED );
  2227.  
  2228.         // Set selected size parameter if movie is a standard size
  2229.         if( IsIconic( hwndMovie ))
  2230.             wSelectedSize = 0;
  2231.         else {
  2232.             GetMovieBox( pMovieData->mMovie, &rcMovie );
  2233.             wMovieWidth  = rcMovie.right - rcMovie.left;
  2234.             wMovieHeight = rcMovie.bottom - rcMovie.top;
  2235.  
  2236.             if( ( wMovieWidth == pMovieData->cx ) &&
  2237.                 ( wMovieHeight == pMovieData->cy ))
  2238.                 wSelectedSize = PLAYER_MOVIE_NORMALSIZE;
  2239.             else if( ( wMovieWidth == pMovieData->cx * 2 ) &&
  2240.                 ( wMovieHeight == pMovieData->cy * 2 ))
  2241.                 wSelectedSize = PLAYER_MOVIE_DOUBLESIZE;
  2242.             else if( ( wMovieWidth == pMovieData->cx / 2 ) &&
  2243.                 ( wMovieHeight == pMovieData->cy / 2 ))
  2244.                 wSelectedSize = PLAYER_MOVIE_HALFSIZE;
  2245.             else
  2246.                 wSelectedSize = 0;
  2247.         }
  2248.  
  2249.         CheckMenuItem( hmenuPopup, PLAYER_MOVIE_HALFSIZE,
  2250.             ( !pMovieData->bSoundOnly &&
  2251.             ( wSelectedSize == PLAYER_MOVIE_HALFSIZE)) ?
  2252.             MF_CHECKED: MF_UNCHECKED );
  2253.         CheckMenuItem( hmenuPopup, PLAYER_MOVIE_NORMALSIZE,
  2254.             ( !pMovieData->bSoundOnly &&
  2255.             ( wSelectedSize == PLAYER_MOVIE_NORMALSIZE)) ?
  2256.             MF_CHECKED: MF_UNCHECKED );
  2257.         CheckMenuItem( hmenuPopup, PLAYER_MOVIE_DOUBLESIZE,
  2258.             ( !pMovieData->bSoundOnly &&
  2259.             ( wSelectedSize == PLAYER_MOVIE_DOUBLESIZE)) ?
  2260.             MF_CHECKED: MF_UNCHECKED );
  2261.  
  2262.         EnableMenuItem( hmenuPopup, PLAYER_MOVIE_SHOWPOSTER,
  2263.             pMovieData->bSoundOnly ? MF_GRAYED: MF_ENABLED );
  2264.  
  2265.         EnableMenuItem( hmenuPopup, PLAYER_MOVIE_SEARCH,
  2266.             GetMovieIndTrackType(pMovieData->mMovie,1,TextMediaType,movieTrackMediaType)?
  2267.             MF_ENABLED: MF_GRAYED );
  2268.     }
  2269.  
  2270.     return 0L;
  2271. }
  2272.  
  2273.  
  2274. // Function: ResizeMovieAndWindow - Resizes the movie and window to the
  2275. //                                  input width and height if flag is TRUE
  2276. //                                  Otherwise resize window to match movie
  2277. // --------------------------------------------------------------------
  2278. // Parameters: HWND         hwndMovie       Handle of Movie window
  2279. //             BOOL         bResizeMovie    TRUE if movie should be resized
  2280. //                                          This will be FALSE when the grow
  2281. //                                          box is used to resize since the
  2282. //                                          movie will already be resized
  2283. //             NPMOVIEDATA  pMovieData      -> to movie data struct
  2284. //             WORD         wMovieWidth     width of movie
  2285. //             WORD         wMovieHeight    height of movie
  2286. //
  2287. // Returns:    LONG         0L if successful
  2288. // --------------------------------------------------------------------
  2289. static LONG NEAR ResizeMovieAndWindow( HWND hwndMovie, BOOL bResizeMovie,
  2290.                NPMOVIEDATA pMovieData, WORD wMovieWidth, WORD wMovieHeight )
  2291.  
  2292. {
  2293.     RECT          rcWindow;     // Window rect
  2294.     RECT          rcWindowPrev; // Prev Window rect
  2295.     RECT          rcBounds;     // Bounds rect
  2296.     POINT         ptCorner;     // Upper-Left corner of window
  2297.     LONG          lError;       // Error return
  2298.     POINT         ptTemp[2];    // Temp array of points
  2299.  
  2300.  
  2301.     if( bResizeMovie &&
  2302.         ( lError = ResizeMovie( pMovieData, wMovieWidth, wMovieHeight )))
  2303.         return lError;
  2304.  
  2305.     // Now Get the bounds rect. In this app, this is the same as the
  2306.     // client rect of the window
  2307.     MCGetControllerBoundsRect( pMovieData->mcMovieController, &rcBounds );
  2308.  
  2309.     // Set about resizing window
  2310.     // Save the prev window rect in client window coordinates
  2311.     GetWindowRect( hwndMovie, &rcWindow );
  2312.     MapWindowPoints( HWND_DESKTOP, PlayerQueryClientWindow(),
  2313.         (LPPOINT) &rcWindow, 2 );
  2314.     rcWindowPrev = rcWindow;
  2315.     ptCorner = *((LPPOINT) &rcWindow );
  2316.  
  2317.     // Adjust corner. This will only happen if window has been
  2318.     // moved using the grow box
  2319.     if( !bResizeMovie && ( rcBounds.left || rcBounds.top )) {
  2320.         ptTemp[0].x = ptTemp[0].y = 0;
  2321.         ptTemp[1] = *((LPPOINT) &rcBounds );
  2322.         MapWindowPoints( hwndMovie, PlayerQueryClientWindow(), ptTemp, 2 );
  2323.  
  2324.         ptCorner.x += ptTemp[1].x - ptTemp[0].x;
  2325.         ptCorner.y += ptTemp[1].y - ptTemp[0].y;
  2326.     }
  2327.  
  2328.     rcWindow = rcBounds;
  2329.     AdjustWindowRect( &rcWindow,
  2330.         GetWindowLong( hwndMovie, GWL_STYLE ), FALSE );
  2331.     // rcWindow contains the new size of the window.
  2332.     // Now offset to the corrent UL corner
  2333.     OffsetRect( &rcWindow, ptCorner.x - rcWindow.left,
  2334.         ptCorner.y - rcWindow.top );
  2335.  
  2336.     // If window rect has changed, resize after
  2337.     // disabling the WM_SIZE processing
  2338.     if( !EqualRect( &rcWindow, &rcWindowPrev )) {
  2339.         pMovieData->bDisableSizeMsgProcessing = TRUE;
  2340.  
  2341.         MoveWindow( hwndMovie, rcWindow.left, rcWindow.top,
  2342.             rcWindow.right - rcWindow.left,
  2343.             rcWindow.bottom - rcWindow.top, TRUE );
  2344.         // If if happens that after resizing, the movie is smaller than
  2345.         // minimum movie window size, resize movie to fill the window
  2346.         GetClientRect( hwndMovie, &rcWindow );
  2347.         if( !EqualRect( &rcWindow, &rcBounds )) {
  2348.             pMovieData->bSettingControllerSize = TRUE;
  2349.             MCSetControllerBoundsRect
  2350.                 ( pMovieData->mcMovieController, &rcWindow );
  2351.         }
  2352.     }
  2353.  
  2354.     return 0L;
  2355. }
  2356.  
  2357.  
  2358. // Function: ResizeMovie - Resizes the movie to the given size
  2359. // --------------------------------------------------------------------
  2360. // Parameters: NPMOVIEDATA  pMovieData      Pointer to movie data struct
  2361. //             WORD         wMovieWidth     width of movie
  2362. //             WORD         wMovieHeight    height of movie
  2363. //
  2364. // Returns:    LONG         0L if successful
  2365. // --------------------------------------------------------------------
  2366. static LONG NEAR ResizeMovie( NPMOVIEDATA pMovieData,
  2367.                                  WORD wMovieWidth, WORD wMovieHeight )
  2368.  
  2369. {
  2370.     RECT     rcBounds; // Controller bounds rect
  2371.  
  2372.     // set based on input movie dimensions.
  2373.     // Need to add in controller height for bounds rect
  2374.     rcBounds.left = rcBounds.top = 0;
  2375.     rcBounds.right  = wMovieWidth;
  2376.     rcBounds.bottom = wMovieHeight + g.wMovieControllerHeight;
  2377.  
  2378.     pMovieData->bSettingControllerSize = TRUE;
  2379.     MCSetControllerBoundsRect( pMovieData->mcMovieController, &rcBounds );
  2380.  
  2381.     if( pMovieData->hwndGetInfo && !g.bUpdatingInfo ) { // WM_PLAYER_INFO_UPDATE is defined to be in the range WM_COALESCE_FIRST
  2382.                                                         // to WM_COALESCE_LAST which tells Windows to prevent duplicate messages
  2383.                                                         // from appearing in the queue.
  2384.         PostMessage( pMovieData->hwndGetInfo, WM_PLAYER_INFO_UPDATE, 0, 0L );
  2385.     }
  2386.  
  2387.     return 0L;
  2388. }
  2389.  
  2390.  
  2391. // Function: UpdateGBBoundsRect - Updates the grow box bounds rect
  2392. // --------------------------------------------------------------------
  2393. // Parameters: HWND            hwndMovie     Handle of movie window
  2394. //             NPMOVIEDATA     pMovieData    -> movie data struct
  2395. //
  2396. // Returns:    VOID
  2397. // --------------------------------------------------------------------
  2398. static VOID NEAR UpdateGBBoundsRect( HWND hwndMovie, NPMOVIEDATA pMovieData )
  2399.  
  2400. {
  2401.     GetClientRect( PlayerQueryFrameWindow(), &pMovieData->rcGrowBox );
  2402.     MapWindowPoints( PlayerQueryFrameWindow(),
  2403.         hwndMovie, (LPPOINT) &pMovieData->rcGrowBox , 2 );
  2404.     MCDoAction( pMovieData->mcMovieController,
  2405.         mcActionSetGrowBoxBounds, &pMovieData->rcGrowBox );
  2406.  
  2407.     return;
  2408.  
  2409. }
  2410.  
  2411.  
  2412. // Function: MakeAnArialFont - Creates a logical font
  2413. // --------------------------------------------------------------------
  2414. // Parameters: HDC           hdc              Device context
  2415. //             int           nTextSize        Size of font
  2416. //
  2417. // Returns:    HFONT         hFont
  2418. //           Note: It is up to the caller to eventually delete this font
  2419. // --------------------------------------------------------------------
  2420. static HFONT NEAR MakeAnArialFont( HDC hdc, int nTextSize )
  2421.  
  2422. {
  2423.     HFONT       hFont; // Handle to created font
  2424.     PLOGFONT    plf;   // -> to font struct
  2425.  
  2426.     if( !(plf = (PLOGFONT) LocalAlloc( LPTR, sizeof( LOGFONT ))))
  2427.         return NULL;
  2428.  
  2429.     plf->lfHeight         = nTextSize;
  2430.     plf->lfWeight         = FW_LIGHT;
  2431.     plf->lfOutPrecision   = OUT_TT_ONLY_PRECIS;
  2432.     plf->lfPitchAndFamily = FF_SWISS;
  2433.     LoadString( PlayerQueryResources(), PLAYER_STRING_FACENAME,
  2434.         plf->lfFaceName, sizeof( plf->lfFaceName ));
  2435.  
  2436.     hFont = CreateFontIndirect( plf );
  2437.  
  2438.     LocalFree( (LOCALHANDLE) plf );
  2439.  
  2440.     return hFont;
  2441. }
  2442.  
  2443.  
  2444. // Function: InitializeResize - Tests for constrained resize and
  2445. //                              sets dragging rect if true
  2446. // --------------------------------------------------------------------
  2447. // Parameters: HWND          hwndMovie        Handle of movie wnd
  2448. //             NPMOVIEDATA   pMovieData       -> movie data struct
  2449. //             WORD          wHitTestCode     NC hit test code
  2450. //             POINT         ptCursor         Position of cursor in
  2451. //                                            screen coordinates
  2452. //
  2453. // Returns:    WORD          wHitTestCode if in border, else 0
  2454. // --------------------------------------------------------------------
  2455. static WORD NEAR InitializeResize
  2456.           ( HWND hwndMovie, NPMOVIEDATA pMovieData,
  2457.                                 WORD wHitTestCode, POINT ptCursor )
  2458.  
  2459. {
  2460.     RECT        rcClipCursor;  // Rect used to clip motion of cursor
  2461.     MINMAXINFO  mmiMinMaxInfo; // Minmax info struct
  2462.  
  2463.  
  2464.     GetWindowRect( hwndMovie, &g.rcResizeRect );
  2465.     GetWindowRect( PlayerQueryClientWindow(), &rcClipCursor );
  2466.  
  2467.     SetMinMaxInfo( hwndMovie, pMovieData, &mmiMinMaxInfo );
  2468.  
  2469.     switch( wHitTestCode ) {
  2470.         case HTTOP:
  2471.             g.ptCursorOffset.x = 0;
  2472.             g.ptCursorOffset.y = g.rcResizeRect.top - ptCursor.y;
  2473.  
  2474.             rcClipCursor.bottom = g.rcResizeRect.bottom -
  2475.                 mmiMinMaxInfo.ptMinTrackSize.y;
  2476.             break;
  2477.         case HTBOTTOM:
  2478.             g.ptCursorOffset.x = 0;
  2479.             g.ptCursorOffset.y = g.rcResizeRect.bottom - ptCursor.y;
  2480.  
  2481.             rcClipCursor.top = g.rcResizeRect.top +
  2482.                 mmiMinMaxInfo.ptMinTrackSize.y;
  2483.             break;
  2484.         case HTLEFT:
  2485.             g.ptCursorOffset.x = g.rcResizeRect.left - ptCursor.x;
  2486.             g.ptCursorOffset.y = 0;
  2487.  
  2488.             rcClipCursor.right = g.rcResizeRect.right -
  2489.                 mmiMinMaxInfo.ptMinTrackSize.x;
  2490.             break;
  2491.         case HTRIGHT:
  2492.             g.ptCursorOffset.x = g.rcResizeRect.right - ptCursor.x;
  2493.             g.ptCursorOffset.y = 0;
  2494.  
  2495.             rcClipCursor.left = g.rcResizeRect.left +
  2496.                 mmiMinMaxInfo.ptMinTrackSize.x;
  2497.             break;
  2498.         case HTTOPLEFT:
  2499.             g.ptCursorOffset.x = g.rcResizeRect.left - ptCursor.x;
  2500.             g.ptCursorOffset.y = g.rcResizeRect.top - ptCursor.y;
  2501.  
  2502.             rcClipCursor.right  = g.rcResizeRect.right -
  2503.                 mmiMinMaxInfo.ptMinTrackSize.x;
  2504.             if( !pMovieData->bSoundOnly )
  2505.                 rcClipCursor.bottom = g.rcResizeRect.bottom -
  2506.                 mmiMinMaxInfo.ptMinTrackSize.y;
  2507.             break;
  2508.         case HTBOTTOMRIGHT:
  2509.             g.ptCursorOffset.x = g.rcResizeRect.right - ptCursor.x;
  2510.             g.ptCursorOffset.y = g.rcResizeRect.bottom - ptCursor.y;
  2511.  
  2512.             rcClipCursor.left = g.rcResizeRect.left +
  2513.                 mmiMinMaxInfo.ptMinTrackSize.x;
  2514.             if( !pMovieData->bSoundOnly )
  2515.                 rcClipCursor.top  = g.rcResizeRect.top +
  2516.                 mmiMinMaxInfo.ptMinTrackSize.y;
  2517.             break;
  2518.         case HTTOPRIGHT:
  2519.             g.ptCursorOffset.x = g.rcResizeRect.right - ptCursor.x;
  2520.             g.ptCursorOffset.y = g.rcResizeRect.top - ptCursor.y;
  2521.  
  2522.             rcClipCursor.left   = g.rcResizeRect.left +
  2523.                 mmiMinMaxInfo.ptMinTrackSize.x;
  2524.             if( !pMovieData->bSoundOnly )
  2525.                 rcClipCursor.bottom = g.rcResizeRect.bottom -
  2526.                 mmiMinMaxInfo.ptMinTrackSize.y;
  2527.             break;
  2528.         case HTBOTTOMLEFT:
  2529.             g.ptCursorOffset.x = g.rcResizeRect.left - ptCursor.x;
  2530.             g.ptCursorOffset.y = g.rcResizeRect.bottom - ptCursor.y;
  2531.  
  2532.             rcClipCursor.right = g.rcResizeRect.right -
  2533.                 mmiMinMaxInfo.ptMinTrackSize.x;
  2534.             if( !pMovieData->bSoundOnly )
  2535.                 rcClipCursor.top   = g.rcResizeRect.top +
  2536.                 mmiMinMaxInfo.ptMinTrackSize.y;
  2537.             break;
  2538.  
  2539.         default:
  2540.             return 0;
  2541.     }
  2542.  
  2543.  
  2544.     if( pMovieData->bSoundOnly ) {
  2545.         SetCursor( g.hcursor = LoadCursor( NULL, IDC_SIZEWE ));
  2546.     }
  2547.     else {
  2548.         SetCursor( g.hcursor = SetCursor( NULL ));
  2549.     }
  2550.     ClipCursor( &rcClipCursor );
  2551.  
  2552.     g.wScaleWidth  = max( pMovieData->cx / 2, 1 );
  2553.     g.wScaleHeight = max( pMovieData->cy / 2, 1 );
  2554.  
  2555.     return wHitTestCode;
  2556. }
  2557.  
  2558.  
  2559. // Function: MoveTheMovieResizeRect - Moves the resizing frame
  2560. // --------------------------------------------------------------------
  2561. // Parameters: HWND          hwndMovie       Handle of movie window
  2562. //             NPMOVIEDATA   pMovieData      -> movie data struct
  2563. //             WORD          wHitTestCode    Hit test code
  2564. //             POINT         ptCursor        Current cursor position in
  2565. //                                           screen coordinates
  2566. //             BOOL          bStarting       TRUE if this is the first
  2567. //                                           call of a drag
  2568. //
  2569. // Returns:    VOID
  2570. // --------------------------------------------------------------------
  2571. static VOID NEAR MoveTheMovieResizeRect
  2572.          ( HWND hwndMovie, NPMOVIEDATA pMovieData,
  2573.                 WORD wHitTestCode, POINT ptCursor, BOOL bStarting )
  2574.  
  2575. {
  2576.     RECT     rcNewRect;    // resize rect in screen coordinates
  2577.     WORD     wMovieWidth;  // Movie width
  2578.     WORD     wMovieHeight; // Movie height
  2579.  
  2580.     ptCursor.x += g.ptCursorOffset.x;
  2581.     ptCursor.y += g.ptCursorOffset.y;
  2582.  
  2583.     rcNewRect = g.rcResizeRect;
  2584.     switch( wHitTestCode ) {
  2585.         case HTTOP:
  2586.             if( !ISKEYDOWN( VK_CONTROL ) && !ISKEYDOWN( VK_SHIFT )) {
  2587.                 rcNewRect.top = ptCursor.y;
  2588.             }
  2589.             else {
  2590.                 wMovieHeight = rcNewRect.bottom - ptCursor.y -
  2591.                     g.wTopAndBottom;
  2592.                 if( ISKEYDOWN( VK_CONTROL )) {
  2593.                     wMovieHeight = g.wScaleHeight *
  2594.                         max( wMovieHeight / g.wScaleHeight, 1 );
  2595.  
  2596.                     if( abs( wMovieHeight -
  2597.                         pMovieData->cy ) <= 2 ) {
  2598.                         wMovieWidth  = pMovieData->cx;
  2599.                         wMovieHeight = pMovieData->cy;
  2600.                     }
  2601.                     else {
  2602.                         wMovieWidth = MulDiv( wMovieHeight,
  2603.                             pMovieData->cx,
  2604.                             pMovieData->cy );
  2605.                     }
  2606.                 }
  2607.                 else {
  2608.                     wMovieWidth = MulDiv( wMovieHeight,
  2609.                         pMovieData->cx,
  2610.                         pMovieData->cy );
  2611.                 }
  2612.  
  2613.                 rcNewRect.right = rcNewRect.left + g.wSides + wMovieWidth;
  2614.                 rcNewRect.top   = rcNewRect.bottom -
  2615.                     g.wTopAndBottom - wMovieHeight;
  2616.             }
  2617.             break;
  2618.         case HTBOTTOM:
  2619.             if( !ISKEYDOWN( VK_CONTROL ) && !ISKEYDOWN( VK_SHIFT )) {
  2620.                 rcNewRect.bottom = ptCursor.y;
  2621.             }
  2622.             else {
  2623.                 wMovieHeight = ptCursor.y - rcNewRect.top - g.wTopAndBottom;
  2624.                 if( ISKEYDOWN( VK_CONTROL )) {
  2625.                     wMovieHeight = g.wScaleHeight *
  2626.                         max( wMovieHeight / g.wScaleHeight, 1 );
  2627.                     if( abs( wMovieHeight -
  2628.                         pMovieData->cy ) <= 2 ) {
  2629.                         wMovieWidth  = pMovieData->cx;
  2630.                         wMovieHeight = pMovieData->cy;
  2631.                     }
  2632.                     else {
  2633.                         wMovieWidth = MulDiv( wMovieHeight,
  2634.                             pMovieData->cx,
  2635.                             pMovieData->cy );
  2636.                     }
  2637.                 }
  2638.                 else {
  2639.                     wMovieWidth = MulDiv( wMovieHeight,
  2640.                         pMovieData->cx,
  2641.                         pMovieData->cy );
  2642.                 }
  2643.  
  2644.                 rcNewRect.right  = rcNewRect.left + g.wSides + wMovieWidth;
  2645.                 rcNewRect.bottom = rcNewRect.top +
  2646.                     g.wTopAndBottom + wMovieHeight;
  2647.             }
  2648.             break;
  2649.         case HTLEFT:
  2650.             if( pMovieData->bSoundOnly ||
  2651.                 ( !ISKEYDOWN( VK_CONTROL ) && !ISKEYDOWN( VK_SHIFT ))) {
  2652.                 rcNewRect.left = ptCursor.x;
  2653.             }
  2654.             else {
  2655.                 wMovieWidth = rcNewRect.right - ptCursor.x - g.wSides;
  2656.                 if( ISKEYDOWN( VK_CONTROL )) {
  2657.                     wMovieWidth = g.wScaleWidth *
  2658.                         max( wMovieWidth / g.wScaleWidth, 1 );
  2659.                     if( abs( wMovieWidth -
  2660.                         pMovieData->cx ) <= 2 ) {
  2661.                         wMovieWidth  = pMovieData->cx;
  2662.                         wMovieHeight = pMovieData->cy;
  2663.                     }
  2664.                     else {
  2665.                         wMovieHeight = MulDiv( wMovieWidth,
  2666.                             pMovieData->cy,
  2667.                             pMovieData->cx );
  2668.                     }
  2669.                 }
  2670.                 else {
  2671.                     wMovieHeight = MulDiv( wMovieWidth,
  2672.                         pMovieData->cy,
  2673.                         pMovieData->cx );
  2674.                 }
  2675.  
  2676.                 rcNewRect.left   = rcNewRect.right - g.wSides - wMovieWidth;
  2677.                 rcNewRect.bottom = rcNewRect.top +
  2678.                     g.wTopAndBottom + wMovieHeight;
  2679.             }
  2680.             break;
  2681.         case HTRIGHT:
  2682.             if( pMovieData->bSoundOnly ||
  2683.                 ( !ISKEYDOWN( VK_CONTROL ) && !ISKEYDOWN( VK_SHIFT ))) {
  2684.                 rcNewRect.right = ptCursor.x;
  2685.             }
  2686.             else {
  2687.                 wMovieWidth = ptCursor.x - rcNewRect.left - g.wSides;
  2688.                 if( ISKEYDOWN( VK_CONTROL )) {
  2689.                     wMovieWidth = g.wScaleWidth *
  2690.                         max( wMovieWidth / g.wScaleWidth, 1 );
  2691.                     if( abs( wMovieWidth -
  2692.                         pMovieData->cx ) <= 2 ) {
  2693.                         wMovieWidth  = pMovieData->cx;
  2694.                         wMovieHeight = pMovieData->cy;
  2695.                     }
  2696.                     else {
  2697.                         wMovieHeight = MulDiv( wMovieWidth,
  2698.                             pMovieData->cy,
  2699.                             pMovieData->cx );
  2700.                     }
  2701.                 }
  2702.                 else {
  2703.                     wMovieHeight = MulDiv( wMovieWidth,
  2704.                         pMovieData->cy,
  2705.                         pMovieData->cx );
  2706.                 }
  2707.  
  2708.                 rcNewRect.right  = rcNewRect.left + g.wSides + wMovieWidth;
  2709.                 rcNewRect.bottom = rcNewRect.top +
  2710.                     g.wTopAndBottom + wMovieHeight;
  2711.             }
  2712.             break;
  2713.         case HTTOPLEFT:
  2714.             if( pMovieData->bSoundOnly ) {
  2715.                 rcNewRect.left = ptCursor.x;
  2716.             }
  2717.             else if( !ISKEYDOWN( VK_CONTROL ) && !ISKEYDOWN( VK_SHIFT )) {
  2718.                 *((LPPOINT) &rcNewRect.left) = ptCursor;
  2719.             }
  2720.             else {
  2721.                 wMovieWidth  = rcNewRect.right - ptCursor.x - g.wSides;
  2722.                 wMovieHeight = rcNewRect.bottom - ptCursor.y -
  2723.                     g.wTopAndBottom;
  2724.                 GetProportionalDimensions( pMovieData,
  2725.                     &wMovieWidth, &wMovieHeight, ISKEYDOWN( VK_CONTROL ));
  2726.                 rcNewRect.top = rcNewRect.bottom - wMovieHeight -
  2727.                     g.wTopAndBottom;
  2728.                 rcNewRect.left = rcNewRect.right - wMovieWidth - g.wSides;
  2729.             }
  2730.             break;
  2731.         case HTBOTTOMRIGHT:
  2732.             if( pMovieData->bSoundOnly ) {
  2733.                 rcNewRect.right = ptCursor.x;
  2734.             }
  2735.             else if( !ISKEYDOWN( VK_CONTROL ) && !ISKEYDOWN( VK_SHIFT )) {
  2736.                 *((LPPOINT) &rcNewRect.right) = ptCursor;
  2737.             }
  2738.             else {
  2739.                 wMovieWidth  = ptCursor.x - rcNewRect.left - g.wSides;
  2740.                 wMovieHeight = ptCursor.y - rcNewRect.top - g.wTopAndBottom;
  2741.                 GetProportionalDimensions( pMovieData,
  2742.                     &wMovieWidth, &wMovieHeight, ISKEYDOWN( VK_CONTROL ));
  2743.                 rcNewRect.bottom = rcNewRect.top + wMovieHeight +
  2744.                     g.wTopAndBottom;
  2745.                 rcNewRect.right = rcNewRect.left + wMovieWidth + g.wSides;
  2746.             }
  2747.             break;
  2748.         case HTTOPRIGHT:
  2749.             if( pMovieData->bSoundOnly ) {
  2750.                 rcNewRect.right = ptCursor.x;
  2751.             }
  2752.             else if( !ISKEYDOWN( VK_CONTROL ) && !ISKEYDOWN( VK_SHIFT )) {
  2753.                 rcNewRect.right = ptCursor.x;
  2754.                 rcNewRect.top   = ptCursor.y;
  2755.             }
  2756.             else {
  2757.                 wMovieWidth  = ptCursor.x - rcNewRect.left - g.wSides;
  2758.                 wMovieHeight = rcNewRect.bottom -
  2759.                     ptCursor.y - g.wTopAndBottom;
  2760.                 GetProportionalDimensions( pMovieData,
  2761.                     &wMovieWidth, &wMovieHeight, ISKEYDOWN( VK_CONTROL ));
  2762.                 rcNewRect.top = rcNewRect.bottom - wMovieHeight -
  2763.                     g.wTopAndBottom;
  2764.                 rcNewRect.right = rcNewRect.left + wMovieWidth + g.wSides;
  2765.             }
  2766.             break;
  2767.         case HTBOTTOMLEFT:
  2768.             if( pMovieData->bSoundOnly ) {
  2769.                 rcNewRect.left = ptCursor.x;
  2770.             }
  2771.             else if( !ISKEYDOWN( VK_CONTROL ) && !ISKEYDOWN( VK_SHIFT )) {
  2772.                 rcNewRect.left   = ptCursor.x;
  2773.                 rcNewRect.bottom = ptCursor.y;
  2774.             }
  2775.             else {
  2776.                 wMovieWidth  = rcNewRect.right - ptCursor.x - g.wSides;
  2777.                 wMovieHeight = ptCursor.y - rcNewRect.top - g.wTopAndBottom;
  2778.                 GetProportionalDimensions( pMovieData,
  2779.                     &wMovieWidth, &wMovieHeight, ISKEYDOWN( VK_CONTROL ));
  2780.                 rcNewRect.bottom = rcNewRect.top + wMovieHeight +
  2781.                     g.wTopAndBottom;
  2782.                 rcNewRect.left = rcNewRect.right - wMovieWidth - g.wSides;
  2783.             }
  2784.             break;
  2785.     }
  2786.  
  2787.     if( bStarting ) {
  2788.         g.rcResizeRect = rcNewRect;
  2789.         g.bFatResizeBorder = IsNormalSize( &g.rcResizeRect, pMovieData );
  2790.         DrawTheFrameRect( &g.rcResizeRect, g.bFatResizeBorder );
  2791.     }
  2792.     else if( !EqualRect( &g.rcResizeRect, &rcNewRect )) {
  2793.         DrawTheFrameRect( &g.rcResizeRect, g.bFatResizeBorder );
  2794.         g.rcResizeRect = rcNewRect;
  2795.         g.bFatResizeBorder = IsNormalSize( &g.rcResizeRect, pMovieData );
  2796.         DrawTheFrameRect( &g.rcResizeRect, g.bFatResizeBorder );
  2797.     }
  2798.  
  2799.     return;
  2800. }
  2801.  
  2802.  
  2803. // Function: AdjustForMinProportionalSize - Adjusts the final dimensions of a movie
  2804. //                                          when a dimension is less than a minimum
  2805. //                                          allowed size
  2806. // --------------------------------------------------------------------
  2807. // Parameters: HWND             hwndMovie      Handle of movie wnd
  2808. //             NPMOVIEDATA      pMovieData     -> movie data struct
  2809. //             LPWORD           lpwWidth;      -> window width
  2810. //             LPWORD           lpwHeight;     -> window height
  2811. //             BOOL             bCtrlKeyDown   TRUE if CONTROL key is down
  2812. //
  2813. // Returns:    VOID
  2814. // --------------------------------------------------------------------
  2815. static VOID NEAR AdjustForMinProportionalSize
  2816.           ( HWND hwndMovie, NPMOVIEDATA pMovieData,
  2817.                  LPWORD lpwWidth, LPWORD lpwHeight, BOOL bCtrlKeyDown )
  2818.  
  2819. {
  2820.     MINMAXINFO  mmiMinMaxInfo; // Minmax info struct
  2821.     WORD        wMovieWidth;   // Movie width
  2822.     WORD        wMovieHeight;  // Movie height
  2823.  
  2824.  
  2825.     SetMinMaxInfo( hwndMovie, pMovieData, &mmiMinMaxInfo );
  2826.     // Add resizing borders
  2827.     mmiMinMaxInfo.ptMinTrackSize.x += g.wSides;
  2828.     mmiMinMaxInfo.ptMinTrackSize.y += g.wTBBorder;
  2829.  
  2830.     if( ( *lpwWidth > (WORD) mmiMinMaxInfo.ptMinTrackSize.x ) &&
  2831.         ( *lpwHeight > (WORD) mmiMinMaxInfo.ptMinTrackSize.y ))
  2832.         return;
  2833.  
  2834.     if( *lpwWidth < (WORD) mmiMinMaxInfo.ptMinTrackSize.x ) {
  2835.         *lpwWidth = mmiMinMaxInfo.ptMinTrackSize.x;
  2836.     }
  2837.     if( *lpwHeight < (WORD) mmiMinMaxInfo.ptMinTrackSize.y ) {
  2838.         *lpwHeight = mmiMinMaxInfo.ptMinTrackSize.y;
  2839.     }
  2840.  
  2841.     // Mult by 10 because numbers may be small
  2842.     wMovieWidth  = ( *lpwWidth - g.wSides ) * 10;
  2843.     wMovieHeight = ( *lpwHeight - g.wTopAndBottom ) * 10;
  2844.     GetProportionalDimensions
  2845.         ( pMovieData, &wMovieWidth, &wMovieHeight, bCtrlKeyDown );
  2846.     *lpwWidth  = ( wMovieWidth + 10 * g.wSides ) / 10;
  2847.     *lpwHeight = ( wMovieHeight + 10 * g.wTopAndBottom ) / 10;
  2848.  
  2849.     return;
  2850.  
  2851. }
  2852.  
  2853.  
  2854. // Function: GetProportionalDimensions - Scales the dimensions of a movie to
  2855. //                                       be in the same proportions as the
  2856. //                                       original movie dimensions
  2857. // --------------------------------------------------------------------
  2858. // Parameters: NPMOVIEDATA    pMovieData        -> movie data struct
  2859. //             PWORD          pwMovieWidth      -> current width
  2860. //             PWORD          pwMovieHeight     -> current height
  2861. //             BOOL           bCtrlKeyDown      TRUE if CONTROL key is down
  2862. //
  2863. // Returns:    VOID
  2864. // --------------------------------------------------------------------
  2865. static VOID NEAR GetProportionalDimensions
  2866.       ( NPMOVIEDATA pMovieData, PWORD pwMovieWidth,
  2867.                                 PWORD pwMovieHeight, BOOL bCtrlKeyDown )
  2868.  
  2869. {
  2870.     WORD     wTempHeight; // Temp height
  2871.  
  2872.     wTempHeight = MulDiv( *pwMovieWidth,
  2873.         pMovieData->cy,
  2874.         pMovieData->cx );
  2875.     if( wTempHeight >= *pwMovieHeight ) {
  2876.         *pwMovieHeight = wTempHeight;
  2877.     }
  2878.     else {
  2879.         *pwMovieWidth = MulDiv( *pwMovieHeight,
  2880.             pMovieData->cx,
  2881.             pMovieData->cy );
  2882.     }
  2883.  
  2884.     if( bCtrlKeyDown ) {
  2885.         *pwMovieHeight = g.wScaleHeight *
  2886.             max( *pwMovieHeight / g.wScaleHeight, 1 );
  2887.  
  2888.         if( abs( *pwMovieHeight - pMovieData->cy ) <= 2 ) {
  2889.             *pwMovieWidth  = pMovieData->cx;
  2890.             *pwMovieHeight = pMovieData->cy;
  2891.         }
  2892.         else {
  2893.             *pwMovieWidth = MulDiv( *pwMovieHeight,
  2894.                 pMovieData->cx,
  2895.                 pMovieData->cy );
  2896.         }
  2897.     }
  2898.  
  2899.     return;
  2900. }
  2901.  
  2902.  
  2903. // Function: IsNormalSize - Determines if movie is normal size
  2904. // --------------------------------------------------------------------
  2905. // Parameters: RECT          lprcResizeRect   -> resize rect
  2906. //             NPMOVIEDATA   pMovieData       -> movie data struct
  2907. //
  2908. // Returns:    BOOL     TRUE if input rect has the normal movie dimensions
  2909. // --------------------------------------------------------------------
  2910. static BOOL NEAR IsNormalSize
  2911.                    ( LPRECT lprcResizeRect, NPMOVIEDATA pMovieData )
  2912.  
  2913. {
  2914.     WORD    wMovieWidth;  // Current width of movie
  2915.     WORD    wMovieHeight; // Current height of movie
  2916.  
  2917.     wMovieWidth = lprcResizeRect->right -
  2918.         lprcResizeRect->left - g.wSides;
  2919.     wMovieHeight = lprcResizeRect->bottom -
  2920.         lprcResizeRect->top - g.wTopAndBottom;
  2921.  
  2922.     return ( wMovieWidth == pMovieData->cx ) &&
  2923.         ( wMovieHeight == pMovieData->cy );
  2924. }
  2925.  
  2926.  
  2927. // Function: DrawTheFrameRect - Draws the resizing frame
  2928. // --------------------------------------------------------------------
  2929. // Parameters: RECT      lprcResizeRect     -> resize rect
  2930. //             BOOL      bFatBorder         Flag to draw thicker border
  2931. //
  2932. // Returns:    VOID
  2933. // --------------------------------------------------------------------
  2934. static VOID NEAR DrawTheFrameRect( LPRECT lprcResizeRect, BOOL bFatBorder )
  2935.  
  2936. {
  2937.     HDC            hdc;             // DC of desktop
  2938.     HBRUSH         hbrushSave;      // Prev brush
  2939.     HBITMAP        hbitmapCheckers; // Handle of checkerboard bitmap
  2940.     WORD           wWBorder;        // Width of vertical border
  2941.     WORD           wHBorder;        // Width of horizontal border
  2942.  
  2943.  
  2944.     typedef  BOOL ( CALLBACK* FFRAMEPROC ) (HDC, LPRECT, int, int, DWORD);
  2945.  
  2946.     static  WORD   wBorderWidth;             // Width of vertical resize border
  2947.     static  WORD   wBorderHeight;            // Height of horizontal resize border
  2948.     static  FFRAMEPROC  lpfnFastWindowFrame; // -> FastWindowFrame()
  2949.     static  HBRUSH  hbrushCheckers;          // Handle to frame brush
  2950.  
  2951.     // FastWindowFrame() is an undocumented Windows function
  2952.     // described in "Undocumented Windows" by Andrew Schulman,
  2953.     // David Maxey and Matt Pietrek, Addison Wesley, 1992.
  2954.  
  2955.     if( lprcResizeRect == NULL ) // Clean up
  2956.     {
  2957.         if( hbrushCheckers ) {
  2958.             DeleteObject( hbrushCheckers );
  2959.             hbrushCheckers = NULL;
  2960.         }
  2961.         return;
  2962.     }
  2963.  
  2964.     if( !lpfnFastWindowFrame ) {
  2965.         lpfnFastWindowFrame = (FFRAMEPROC) GetProcAddress(
  2966.             GetModuleHandle( "GDI" ), "FASTWINDOWFRAME" );
  2967.         wBorderWidth  = GetSystemMetrics( SM_CXFRAME ) - 1;
  2968.         wBorderHeight = GetSystemMetrics( SM_CXFRAME ) - 1;
  2969.     }
  2970.  
  2971.     if( !hbrushCheckers &&
  2972.         ( hbitmapCheckers = LoadBitmap( PlayerQueryInstance(),
  2973.         MAKEINTRESOURCE( PLAYER_CHECKERS_BITMAP )))) {
  2974.         hbrushCheckers = CreatePatternBrush( hbitmapCheckers );
  2975.         DeleteObject( hbitmapCheckers );
  2976.     }
  2977.  
  2978.     if( hdc = GetDC( NULL )) {
  2979.         if( lpfnFastWindowFrame ) {
  2980.             if( hbrushCheckers )
  2981.                 hbrushSave = SelectObject( hdc, hbrushCheckers );
  2982.             else
  2983.                 hbrushSave = SelectObject( hdc,
  2984.                 GetStockObject( GRAY_BRUSH ));
  2985.  
  2986.             wWBorder = wBorderWidth  + ( bFatBorder? 2: 0);
  2987.             wHBorder = wBorderHeight + ( bFatBorder? 2: 0);
  2988.  
  2989.             if( !( *lpfnFastWindowFrame ) ( hdc, lprcResizeRect,
  2990.                 wWBorder, wHBorder, PATINVERT )) { // Use PatBlt when FastWindowFrame fails
  2991.                 ExcludeClipRect( hdc,
  2992.                     lprcResizeRect->left + wWBorder,
  2993.                     lprcResizeRect->top  + wHBorder,
  2994.                     lprcResizeRect->right  - wWBorder,
  2995.                     lprcResizeRect->bottom - wHBorder );
  2996.  
  2997.                 PatBlt( hdc, lprcResizeRect->left,
  2998.                     lprcResizeRect->top,
  2999.                     lprcResizeRect->right - lprcResizeRect->left,
  3000.                     lprcResizeRect->bottom - lprcResizeRect->top,
  3001.                     PATINVERT );
  3002.             }
  3003.  
  3004.             if( hbrushSave )
  3005.                 SelectObject( hdc, hbrushSave );
  3006.         }
  3007.         else {
  3008.             DrawFocusRect( hdc, lprcResizeRect );
  3009.         }
  3010.  
  3011.         ReleaseDC( NULL, hdc );
  3012.     }
  3013.  
  3014.     return;
  3015. }
  3016.  
  3017.  
  3018. // Function: SubclassTheGrowBox - Subclass the movie controller grow box
  3019. // --------------------------------------------------------------------
  3020. // Parameters: HWND           hwndMovie    Handle of movie wnd
  3021. //             NPMOVIEDATA    pMovieData   -> movie data struct
  3022. //
  3023. // Returns:    BOOL    TRUE if successful
  3024. // --------------------------------------------------------------------
  3025. static BOOL NEAR SubclassTheGrowBox
  3026.                               ( HWND hwndMovie, NPMOVIEDATA pMovieData )
  3027.  
  3028. {
  3029.     WNDENUMPROC     lpfnEnumProc; // -> enumeration proc
  3030.  
  3031.     if( lpfnEnumProc = (WNDENUMPROC) MakeProcInstance
  3032.         ( (FARPROC) MovieChildEnumProc, PlayerQueryInstance())) {
  3033.         EnumChildWindows( hwndMovie, lpfnEnumProc,
  3034.             MAKELONG( pMovieData, 0 ));
  3035.         FreeProcInstance( (FARPROC) lpfnEnumProc );
  3036.  
  3037.         return pMovieData->bGrowBoxSubclassed;
  3038.     }
  3039.  
  3040.     return FALSE;
  3041. }
  3042.  
  3043.  
  3044. // Function: MovieChildEnumProc - Movie child enumeration proc
  3045. // --------------------------------------------------------------------
  3046. // Parameters: As required by Microsoft Windows
  3047. //
  3048. // Returns:    As required by Microsoft Windows
  3049. // --------------------------------------------------------------------
  3050. BOOL __export CALLBACK MovieChildEnumProc
  3051.                               ( HWND hwndChild, LPARAM lParam )
  3052.  
  3053. {
  3054.     char      szClassName[50]; // Class name buffer
  3055.  
  3056.     // The grow box class name can be found by using the enumeration
  3057.     // routine to list all the names
  3058.     #define GROWBOXCLASSNAME   "MCGrowBox"
  3059.  
  3060.     if( GetClassName( hwndChild,
  3061.         szClassName, sizeof( szClassName )) &&
  3062.         !lstrcmpi( GROWBOXCLASSNAME, szClassName )) {
  3063.         if( g.lpNewGBProc ||
  3064.             ( g.lpNewGBProc = (WNDPROC) MakeProcInstance
  3065.             ( (FARPROC) GBSubClassProc, PlayerQueryInstance()))) {
  3066.             if( g.lpOldGBProc = (WNDPROC) SetWindowLong
  3067.                 ( hwndChild, GWL_WNDPROC, (LONG) g.lpNewGBProc )) {
  3068.                 ((NPMOVIEDATA) LOWORD( lParam ))->
  3069.                     bGrowBoxSubclassed = TRUE;
  3070.             }
  3071.         }
  3072.  
  3073.         return FALSE;
  3074.     }
  3075.  
  3076.     return TRUE;
  3077. }
  3078.  
  3079.  
  3080. // Function: GBSubClassProc - Movie controller grow box subclass
  3081. // --------------------------------------------------------------------
  3082. // Parameters: As required by Microsoft Windows
  3083. //
  3084. // Returns:    As required by Microsoft Windows
  3085. // --------------------------------------------------------------------
  3086. LONG __export CALLBACK GBSubClassProc
  3087.     ( HWND hwndGrowBox, UINT message, WPARAM wParam, LPARAM lParam )
  3088.  
  3089. {
  3090.     POINT    ptCursor; // Cursor position
  3091.  
  3092.     if( g.hwndMaximizedMovie && ( message == WM_LBUTTONDOWN )) {
  3093.         ptCursor = MAKEPOINT( lParam );
  3094.         ClientToScreen( hwndGrowBox, &ptCursor );
  3095.         InitMaxWndGrowBoxResize( hwndGrowBox, ptCursor );
  3096.  
  3097.         SetCapture( g.hwndMaximizedMovie );
  3098.         g.bCapturedGrowBox = TRUE;
  3099.  
  3100.         return 0L;
  3101.     }
  3102.  
  3103.     return CallWindowProc
  3104.         ( g.lpOldGBProc, hwndGrowBox, message, wParam, lParam );
  3105. }
  3106.  
  3107.  
  3108. // Function: InitMaxWndGrowBoxResize - Initializes the maximized window grow
  3109. //                                     box resizing
  3110. // --------------------------------------------------------------------
  3111. // Parameters: HWND        hwndGrowBox    Handle of grow box
  3112. //             POINT       ptCursor       Position of cursor in screen coords.
  3113. //
  3114. // Returns:    BOOL        TRUE if successful
  3115. // --------------------------------------------------------------------
  3116. static BOOL NEAR InitMaxWndGrowBoxResize
  3117.                               ( HWND hwndGrowBox, POINT ptCursor )
  3118.  
  3119. {
  3120.     RECT         rcClipCursor; // Clip cursor rect
  3121.     HDC          hdc;          // DC of desktop
  3122.  
  3123.     GetWindowRect( PlayerQueryFrameWindow(), &g.rcResizeRect );
  3124.     g.ptCursorOffset.x = g.rcResizeRect.right  - ptCursor.x;
  3125.     g.ptCursorOffset.y = g.rcResizeRect.bottom - ptCursor.y;
  3126.  
  3127.     rcClipCursor.left = g.rcResizeRect.left +
  3128.         GetSystemMetrics( SM_CXMINTRACK ) - g.ptCursorOffset.x;
  3129.     rcClipCursor.top  = g.rcResizeRect.top +
  3130.         GetSystemMetrics( SM_CYMINTRACK ) - g.ptCursorOffset.y;
  3131.  
  3132.     // Offset the clip cursor rect to keep frame on screen
  3133.     if( hdc = GetDC( NULL )) {
  3134.         rcClipCursor.right =
  3135.             GetDeviceCaps( hdc, HORZRES ) - g.ptCursorOffset.x;
  3136.         rcClipCursor.bottom =
  3137.             GetDeviceCaps( hdc, VERTRES ) - g.ptCursorOffset.y;
  3138.         ReleaseDC( NULL, hdc );
  3139.     }
  3140.     else {
  3141.         rcClipCursor.right  = 0x7fff;
  3142.         rcClipCursor.bottom = 0x7fff;
  3143.     }
  3144.     ClipCursor( &rcClipCursor );
  3145.  
  3146.     DrawTheFrameRect( &g.rcResizeRect, FALSE );
  3147.  
  3148.     return TRUE;
  3149. }
  3150.  
  3151.  
  3152. // Function: MoveTheFrameResizeRect - Moves the resizing frame during
  3153. //                                    maximized wnd grow box resizing
  3154. // --------------------------------------------------------------------
  3155. // Parameters: HWND          hwndMovie     Handle of movie wnd
  3156. //             POINT         ptCursor      Current cursor position in
  3157. //                                         screen coordinates
  3158. //
  3159. // Returns:    VOID
  3160. // --------------------------------------------------------------------
  3161. static VOID NEAR MoveTheFrameResizeRect
  3162.                           ( HWND hwndMovie, POINT ptCursor )
  3163.  
  3164. {
  3165.     RECT     rcNewRect; // resize rect in screen coordinates
  3166.  
  3167.     ptCursor.x += g.ptCursorOffset.x;
  3168.     ptCursor.y += g.ptCursorOffset.y;
  3169.  
  3170.     rcNewRect = g.rcResizeRect;
  3171.     *((LPPOINT) &rcNewRect.right) = ptCursor;
  3172.  
  3173.     if( !EqualRect( &g.rcResizeRect, &rcNewRect )) {
  3174.         DrawTheFrameRect( &g.rcResizeRect, FALSE );
  3175.         g.rcResizeRect = rcNewRect;
  3176.         DrawTheFrameRect( &g.rcResizeRect, FALSE );
  3177.     }
  3178.  
  3179.     return;
  3180. }
  3181.  
  3182.  
  3183. // Function: FixUpMovieTiling - Sets the dimensions of the movie
  3184. //                              window when tiling
  3185. // --------------------------------------------------------------------
  3186. // Parameters: HWND             hwndMovie      Handle of movie wnd
  3187. //             NPMOVIEDATA      pMovieData     -> movie data struct
  3188. //             LPWINDOWPOS      lpwpWndPos     -> WINDOWPOS struct
  3189. //
  3190. // Returns:    LONG      Always 0L
  3191. // --------------------------------------------------------------------
  3192. static LONG NEAR FixUpMovieTiling
  3193.      ( HWND hwndMovie, NPMOVIEDATA pMovieData, LPWINDOWPOS lpwpWndPos )
  3194.  
  3195. {
  3196.     WORD          wMovieWidthMDI;  // Width of tile region
  3197.     WORD          wMovieHeightMDI; // Height of tile region
  3198.     WORD          wTemp;           // Temp
  3199.     MINMAXINFO    mmiMinMaxInfo;   // MinMax info struct
  3200.  
  3201.  
  3202.     if( pMovieData->bSoundOnly ) {
  3203.         SetMinMaxInfo( hwndMovie, pMovieData, &mmiMinMaxInfo );
  3204.         lpwpWndPos->cx =
  3205.             max( mmiMinMaxInfo.ptMinTrackSize.x,
  3206.             min( (int) g.wSoundOnlyDefWidth, lpwpWndPos->cx ));
  3207.         lpwpWndPos->cy = mmiMinMaxInfo.ptMaxTrackSize.y;
  3208.  
  3209.         return 0L;
  3210.     }
  3211.  
  3212.     wMovieWidthMDI  = lpwpWndPos->cx - g.wSides;
  3213.     wMovieHeightMDI = lpwpWndPos->cy - g.wTopAndBottom;
  3214.  
  3215.     if( ( wMovieWidthMDI >= pMovieData->cx ) &&
  3216.         ( wMovieHeightMDI >= pMovieData->cy )) {
  3217.         lpwpWndPos->cx = pMovieData->cx + g.wSides;
  3218.         lpwpWndPos->cy = pMovieData->cy + g.wTopAndBottom;
  3219.     }
  3220.     else // Try setting height and calc width
  3221.     {
  3222.         wTemp = MulDiv( wMovieHeightMDI,
  3223.             pMovieData->cx,
  3224.             pMovieData->cy );
  3225.         // If it fits, we are done
  3226.         if( wTemp <= wMovieWidthMDI ) {
  3227.             lpwpWndPos->cx = wTemp + g.wSides;
  3228.         }
  3229.         else // Set width and calc height
  3230.         {
  3231.             wTemp = MulDiv( wMovieWidthMDI,
  3232.                 pMovieData->cy,
  3233.                 pMovieData->cx );
  3234.             lpwpWndPos->cy = wTemp + g.wTopAndBottom;
  3235.         }
  3236.  
  3237.         // Now check for min allowed proportional size
  3238.         AdjustForMinProportionalSize( hwndMovie, pMovieData,
  3239.             &lpwpWndPos->cx, &lpwpWndPos->cy, FALSE );
  3240.     }
  3241.  
  3242.     return 0L;
  3243. }
  3244.  
  3245.  
  3246. // Function: SetOptionsDefaults - Set option defaults
  3247. // --------------------------------------------------------------------
  3248. // Parameters: HWND             hwndMovie      Movie hwnd
  3249. //             NPMOVIEDATA      pMovieData     -> movie data struct
  3250. //
  3251. // Returns:    VOID
  3252. // --------------------------------------------------------------------
  3253. static VOID NEAR SetOptionsDefaults
  3254.                               ( HWND hwndMovie, NPMOVIEDATA pMovieData )
  3255.  
  3256. { // Preset copy struct parameters that do not change
  3257.     pMovieData->qtoleOptions.lStructSize     = sizeof( QTOLE_OPTIONSMOVIE );
  3258.     pMovieData->qtoleOptions.lVersion        = VERSION_1;
  3259.     pMovieData->qtoleOptions.wObjectType     = MOVIE_OBJECT;
  3260.     pMovieData->qtoleOptions.hwndObject      = hwndMovie;
  3261.  
  3262.     pMovieData->qtoleOptions.mMovie          = pMovieData->mMovie;
  3263.     pMovieData->qtoleOptions.bSoundOnlyMovie = pMovieData->bSoundOnly;
  3264.     pMovieData->qtoleOptions.lfxRate         = DEFAULT_RATE;
  3265.  
  3266.     pMovieData->qtoleOptions.sizeNormal.cx   = pMovieData->cx;
  3267.     pMovieData->qtoleOptions.sizeNormal.cy   = pMovieData->cy;
  3268.  
  3269.     pMovieData->qtoleOptions.tvMovieDuration =
  3270.         GetMovieDuration( pMovieData->mMovie );
  3271.  
  3272.     // This routine queries qtw.ini for defaults
  3273.     PlayerGetDefaultOptions( &pMovieData->qtoleOptions );
  3274.  
  3275.     if( pMovieData->qtoleOptions.bSizeHalf ) {
  3276.         pMovieData->qtoleOptions.sizeCurrent.cx =
  3277.             pMovieData->qtoleOptions.sizeNormal.cx / 2;
  3278.         pMovieData->qtoleOptions.sizeCurrent.cy =
  3279.             pMovieData->qtoleOptions.sizeNormal.cy / 2;
  3280.     }
  3281.     else if( pMovieData->qtoleOptions.bSizeDouble ) {
  3282.         pMovieData->qtoleOptions.sizeCurrent.cx =
  3283.             pMovieData->qtoleOptions.sizeNormal.cx * 2;
  3284.         pMovieData->qtoleOptions.sizeCurrent.cy =
  3285.             pMovieData->qtoleOptions.sizeNormal.cy * 2;
  3286.     }
  3287.     else // Set to normal size if not half or double
  3288.     {
  3289.         pMovieData->qtoleOptions.sizeCurrent =
  3290.             pMovieData->qtoleOptions.sizeNormal;
  3291.     }
  3292.  
  3293.     lstrcpy( pMovieData->qtoleOptions.szCaption, pMovieData->szMovieName );
  3294.     lstrcat( pMovieData->qtoleOptions.szCaption, pMovieData->szMovieExt );
  3295.  
  3296.     return;
  3297. }
  3298.  
  3299.  
  3300. // Function: UpdateMovieForOptions - Sets movie options according to values
  3301. //                                   set in options dialog
  3302. // --------------------------------------------------------------------
  3303. // Parameters: HWND          hwndMovie;      Movie window handle
  3304. //             NPMOVIEDATA   pMovieData;     Movie data structure
  3305. //             BOOL          bCalledByOLE    TRUE if called by ole callback func.
  3306. //
  3307. // Returns:    None
  3308. // --------------------------------------------------------------------
  3309. VOID FAR UpdateMovieForOptions
  3310.     ( HWND hwndMovie, NPMOVIEDATA pMovieData, BOOL bCalledByOLE )
  3311.  
  3312. {
  3313.     TimeRecord   trTime;
  3314.  
  3315.     if( pMovieData->qtoleOptions.bLoop )
  3316.         SendMessage( hwndMovie, WM_COMMAND, PLAYER_MOVIE_LOOP, 0L );
  3317.     else if( pMovieData->qtoleOptions.bLoopPalindrome )
  3318.         SendMessage( hwndMovie, WM_COMMAND, PLAYER_MOVIE_BACKANDFORTH, 0L );
  3319.     else
  3320.         SendMessage( hwndMovie, WM_COMMAND, PLAYER_MOVIE_STOPATEND, 0L );
  3321.  
  3322.     MCDoAction( pMovieData->mcMovieController,
  3323.         mcActionSetPlaySelection,
  3324.         (LPVOID) pMovieData->qtoleOptions.bPlaySelectionOnly );
  3325.  
  3326.     if( pMovieData->qtoleOptions.bSizeHalf )
  3327.         SendMessage( hwndMovie, WM_COMMAND, PLAYER_MOVIE_HALFSIZE, 0L );
  3328.     else if( pMovieData->qtoleOptions.bSizeNormal )
  3329.         SendMessage( hwndMovie, WM_COMMAND, PLAYER_MOVIE_NORMALSIZE, 0L );
  3330.     else if( pMovieData->qtoleOptions.bSizeDouble )
  3331.         SendMessage( hwndMovie, WM_COMMAND, PLAYER_MOVIE_DOUBLESIZE, 0L );
  3332.     else if( bCalledByOLE )
  3333.         ResizeMovieAndWindow( hwndMovie, TRUE, pMovieData,
  3334.         pMovieData->qtoleOptions.sizeCurrent.cx,
  3335.         pMovieData->qtoleOptions.sizeCurrent.cy );
  3336.  
  3337.     if( bCalledByOLE ) {
  3338.         trTime.value.dwHi = 0L;
  3339.         trTime.value.dwLo = pMovieData->qtoleOptions.tvDisplayFrame;
  3340.         trTime.scale = GetMovieTimeScale( pMovieData->mMovie );
  3341.         trTime.base  = TIMEBASE_DEFAULT;
  3342.  
  3343.         MCDoAction( pMovieData->mcMovieController,
  3344.             mcActionGoToTime, (LPVOID) &trTime );
  3345.  
  3346.         MCDoAction( pMovieData->mcMovieController,
  3347.             mcActionSetSelectionBegin,
  3348.             (LPVOID) &pMovieData->qtoleOptions.trSelStart );
  3349.         MCDoAction( pMovieData->mcMovieController,
  3350.             mcActionSetSelectionDuration,
  3351.             (LPVOID) &pMovieData->qtoleOptions.trSelDuration );
  3352.     }
  3353.  
  3354.     return;
  3355. }
  3356.  
  3357.  
  3358. // Function: PopulateOptionsStruct - Populates the options structure
  3359. // --------------------------------------------------------------------
  3360. // Parameters: HWND          hwndMovie      HWND of movie
  3361. //             NPMOVIEDATA   pMovieData     Movie data structure
  3362. //
  3363. // Returns:    None
  3364. // --------------------------------------------------------------------
  3365. static VOID NEAR PopulateOptionsStruct( HWND hwndMovie, NPMOVIEDATA pMovieData )
  3366.  
  3367. {
  3368.     BOOL           bLoop;           // Looping flag
  3369.     BOOL           bLoopPalindrome; // Loop palindrome flag
  3370.     RECT           rcMovie;         // Movie rectangle
  3371.     WORD           wMovieWidth;     // Movie width
  3372.     WORD           wMovieHeight;    // Movie height
  3373.     TimeRecord     trMovieTime;     // Movie time.. not used
  3374.  
  3375.  
  3376.     // Update these each time in case they get NULLed somewhere
  3377.     pMovieData->qtoleOptions.hwndObject = hwndMovie;
  3378.     pMovieData->qtoleOptions.mMovie     = pMovieData->mMovie;
  3379.  
  3380.     MCDoAction( pMovieData->mcMovieController,
  3381.         mcActionGetLooping, (LPVOID) &bLoop );
  3382.     MCDoAction( pMovieData->mcMovieController,
  3383.         mcActionGetLoopIsPalindrome, (LPVOID) &bLoopPalindrome );
  3384.  
  3385.     pMovieData->qtoleOptions.bLoop           = FALSE;
  3386.     pMovieData->qtoleOptions.bLoopPalindrome = FALSE;
  3387.     if( bLoop ) {
  3388.         if( bLoopPalindrome )
  3389.             pMovieData->qtoleOptions.bLoopPalindrome = TRUE;
  3390.         else
  3391.             pMovieData->qtoleOptions.bLoop = TRUE;
  3392.     }
  3393.  
  3394.     MCDoAction( pMovieData->mcMovieController,
  3395.         mcActionGetPlaySelection,
  3396.         (LPVOID) &pMovieData->qtoleOptions.bPlaySelectionOnly );
  3397.     if( pMovieData->qtoleOptions.bPlaySelectionOnly ) {
  3398.         pMovieData->qtoleOptions.trSelStart = pMovieData->trSelectionStart;
  3399.         pMovieData->qtoleOptions.trSelDuration =
  3400.             pMovieData->trSelectionDuration;
  3401.     }
  3402.     else {
  3403.         memset( &pMovieData->qtoleOptions.trSelStart,
  3404.             0, sizeof( TimeRecord ));
  3405.         memset( &pMovieData->qtoleOptions.trSelDuration,
  3406.             0, sizeof( TimeRecord ));
  3407.     }
  3408.  
  3409.     GetMovieBox( pMovieData->mMovie, &rcMovie );
  3410.     wMovieWidth  = rcMovie.right  - rcMovie.left;
  3411.     wMovieHeight = rcMovie.bottom - rcMovie.top;
  3412.  
  3413.     pMovieData->qtoleOptions.sizeCurrent.cx = wMovieWidth;
  3414.     pMovieData->qtoleOptions.sizeCurrent.cy = wMovieHeight;
  3415.  
  3416.     if( !pMovieData->qtoleOptions.bSoundOnlyMovie ) {
  3417.         if( !pMovieData->qtoleOptions.bCopyCurrentFrame ) {
  3418.             pMovieData->qtoleOptions.tvDisplayFrame =
  3419.                 GetMoviePosterTime( pMovieData->mMovie );
  3420.         }
  3421.         else {
  3422.             pMovieData->qtoleOptions.tvDisplayFrame =
  3423.                 GetMovieTime( pMovieData->mMovie, &trMovieTime );
  3424.         }
  3425.     }
  3426.     else {
  3427.         pMovieData->qtoleOptions.tvDisplayFrame = 0;
  3428.     }
  3429.  
  3430.     return;
  3431. }
  3432.  
  3433.  
  3434. //  This function is a query function called by other modules
  3435.  
  3436. // Function: PlayerQueryActiveMovieName - Query name of active movie
  3437. // --------------------------------------------------------------------
  3438. // Parameters: LPSTR      lpBuffer       string buffer
  3439. //
  3440. // Returns:    LPSTR      lpBuffer       Name of active movie
  3441. // --------------------------------------------------------------------
  3442. LPSTR FAR PlayerQueryActiveMovieName( LPSTR lpBuffer )
  3443.  
  3444. {
  3445.     HWND          hwndMovie;  // Handle to active window
  3446.     NPMOVIEDATA   pMovieData; // ->movie data struct
  3447.  
  3448.     hwndMovie = (HWND) SendMessage
  3449.         ( PlayerQueryClientWindow(), WM_MDIGETACTIVE, 0, 0L );
  3450.     *lpBuffer = 0;
  3451.     if( pMovieData = (NPMOVIEDATA) GetWindowWord( hwndMovie, 0 ))
  3452.         lstrcpy( lpBuffer, pMovieData->szMovieName );
  3453.  
  3454.     return lpBuffer;
  3455. }
  3456.